A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
create-module.py
1 #! /usr/bin/env python
2 import sys
3 from optparse import OptionParser
4 import os
5 
6 
7 WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
8 
9 # def options(opt):
10 # pass
11 
12 # def configure(conf):
13 # conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H')
14 
15 def build(bld):
16  module = bld.create_ns3_module(%(MODULE)r, ['core'])
17  module.source = [
18  'model/%(MODULE)s.cc',
19  'helper/%(MODULE)s-helper.cc',
20  ]
21 
22  module_test = bld.create_ns3_module_test_library('%(MODULE)s')
23  module_test.source = [
24  'test/%(MODULE)s-test-suite.cc',
25  ]
26 
27  headers = bld(features='ns3header')
28  headers.module = %(MODULE)r
29  headers.source = [
30  'model/%(MODULE)s.h',
31  'helper/%(MODULE)s-helper.h',
32  ]
33 
34  if bld.env.ENABLE_EXAMPLES:
35  bld.recurse('examples')
36 
37  # bld.ns3_python_bindings()
38 
39 '''
40 
41 
42 
43 MODEL_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
44 
45 #include "%(MODULE)s.h"
46 
47 namespace ns3 {
48 
49 /* ... */
50 
51 
52 }
53 
54 '''
55 
56 
57 
58 MODEL_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
59 #ifndef %(INCLUDE_GUARD)s
60 #define %(INCLUDE_GUARD)s
61 
62 namespace ns3 {
63 
64 /* ... */
65 
66 }
67 
68 #endif /* %(INCLUDE_GUARD)s */
69 
70 '''
71 
72 
73 
74 HELPER_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
75 
76 #include "%(MODULE)s-helper.h"
77 
78 namespace ns3 {
79 
80 /* ... */
81 
82 
83 }
84 
85 '''
86 
87 
88 
89 HELPER_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
90 #ifndef %(INCLUDE_GUARD)s
91 #define %(INCLUDE_GUARD)s
92 
93 #include "ns3/%(MODULE)s.h"
94 
95 namespace ns3 {
96 
97 /* ... */
98 
99 }
100 
101 #endif /* %(INCLUDE_GUARD)s */
102 
103 '''
104 
105 
106 EXAMPLES_WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
107 
108 def build(bld):
109  obj = bld.create_ns3_program('%(MODULE)s-example', [%(MODULE)r])
110  obj.source = '%(MODULE)s-example.cc'
111 
112 '''
113 
114 EXAMPLE_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
115 
116 #include "ns3/core-module.h"
117 #include "ns3/%(MODULE)s-helper.h"
118 
119 using namespace ns3;
120 
121 
122 int
123 main (int argc, char *argv[])
124 {
125  bool verbose = true;
126 
127  CommandLine cmd;
128  cmd.AddValue ("verbose", "Tell application to log if true", verbose);
129 
130  cmd.Parse (argc,argv);
131 
132  /* ... */
133 
134  Simulator::Run ();
135  Simulator::Destroy ();
136  return 0;
137 }
138 
139 
140 '''
141 
142 
143 TEST_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
144 
145 // Include a header file from your module to test.
146 #include "ns3/%(MODULE)s.h"
147 
148 // An essential include is test.h
149 #include "ns3/test.h"
150 
151 // Do not put your test classes in namespace ns3. You may find it useful
152 // to use the using directive to access the ns3 namespace directly
153 using namespace ns3;
154 
155 // This is an example TestCase.
156 class %(CAPITALIZED)sTestCase1 : public TestCase
157 {
158 public:
159  %(CAPITALIZED)sTestCase1 ();
160  virtual ~%(CAPITALIZED)sTestCase1 ();
161 
162 private:
163  virtual void DoRun (void);
164 };
165 
166 // Add some help text to this case to describe what it is intended to test
167 %(CAPITALIZED)sTestCase1::%(CAPITALIZED)sTestCase1 ()
168  : TestCase ("%(CAPITALIZED)s test case (does nothing)")
169 {
170 }
171 
172 // This destructor does nothing but we include it as a reminder that
173 // the test case should clean up after itself
174 %(CAPITALIZED)sTestCase1::~%(CAPITALIZED)sTestCase1 ()
175 {
176 }
177 
178 //
179 // This method is the pure virtual method from class TestCase that every
180 // TestCase must implement
181 //
182 void
183 %(CAPITALIZED)sTestCase1::DoRun (void)
184 {
185  // A wide variety of test macros are available in src/core/test.h
186  NS_TEST_ASSERT_MSG_EQ (true, true, "true doesn't equal true for some reason");
187  // Use this one for floating point comparisons
188  NS_TEST_ASSERT_MSG_EQ_TOL (0.01, 0.01, 0.001, "Numbers are not equal within tolerance");
189 }
190 
191 // The TestSuite class names the TestSuite, identifies what type of TestSuite,
192 // and enables the TestCases to be run. Typically, only the constructor for
193 // this class must be defined
194 //
195 class %(CAPITALIZED)sTestSuite : public TestSuite
196 {
197 public:
198  %(CAPITALIZED)sTestSuite ();
199 };
200 
201 %(CAPITALIZED)sTestSuite::%(CAPITALIZED)sTestSuite ()
202  : TestSuite ("%(MODULE)s", UNIT)
203 {
204  // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER
205  AddTestCase (new %(CAPITALIZED)sTestCase1, TestCase::QUICK);
206 }
207 
208 // Do not forget to allocate an instance of this TestSuite
209 static %(CAPITALIZED)sTestSuite %(COMPOUND)sTestSuite;
210 
211 '''
212 
213 
214 DOC_RST_TEMPLATE = '''Example Module Documentation
215 ----------------------------
216 
217 .. include:: replace.txt
218 
219 .. heading hierarchy:
220  ------------- Chapter
221  ************* Section (#.#)
222  ============= Subsection (#.#.#)
223  ############# Paragraph (no number)
224 
225 This is a suggested outline for adding new module documentation to |ns3|.
226 See ``src/click/doc/click.rst`` for an example.
227 
228 The introductory paragraph is for describing what this code is trying to
229 model.
230 
231 For consistency (italicized formatting), please use |ns3| to refer to
232 ns-3 in the documentation (and likewise, |ns2| for ns-2). These macros
233 are defined in the file ``replace.txt``.
234 
235 Model Description
236 *****************
237 
238 The source code for the new module lives in the directory ``src/%(MODULE)s``.
239 
240 Add here a basic description of what is being modeled.
241 
242 Design
243 ======
244 
245 Briefly describe the software design of the model and how it fits into
246 the existing ns-3 architecture.
247 
248 Scope and Limitations
249 =====================
250 
251 What can the model do? What can it not do? Please use this section to
252 describe the scope and limitations of the model.
253 
254 References
255 ==========
256 
257 Add academic citations here, such as if you published a paper on this
258 model, or if readers should read a particular specification or other work.
259 
260 Usage
261 *****
262 
263 This section is principally concerned with the usage of your model, using
264 the public API. Focus first on most common usage patterns, then go
265 into more advanced topics.
266 
267 Building New Module
268 ===================
269 
270 Include this subsection only if there are special build instructions or
271 platform limitations.
272 
273 Helpers
274 =======
275 
276 What helper API will users typically use? Describe it here.
277 
278 Attributes
279 ==========
280 
281 What classes hold attributes, and what are the key ones worth mentioning?
282 
283 Output
284 ======
285 
286 What kind of data does the model generate? What are the key trace
287 sources? What kind of logging output can be enabled?
288 
289 Advanced Usage
290 ==============
291 
292 Go into further details (such as using the API outside of the helpers)
293 in additional sections, as needed.
294 
295 Examples
296 ========
297 
298 What examples using this new code are available? Describe them here.
299 
300 Troubleshooting
301 ===============
302 
303 Add any tips for avoiding pitfalls, etc.
304 
305 Validation
306 **********
307 
308 Describe how the model has been tested/validated. What tests run in the
309 test suite? How much API and code is covered by the tests? Again,
310 references to outside published work may help here.
311 '''
312 
313 
314 def main(argv):
315  parser = OptionParser(usage=("Usage: %prog [options] modulename\n"
316  "Utility script to create a basic template for a new ns-3 module"))
317  (options, args) = parser.parse_args()
318  if len(args) != 1:
319  parser.print_help()
320  return 1
321 
322  modname = args[0].lower()
323  if False in [word.isalnum() for word in modname.split("-")]:
324  print >> sys.stderr, "Module name should only contain alphanumeric characters and dashes"
325  return 2
326  assert os.path.sep not in modname
327 
328  moduledir = os.path.join(os.path.dirname(__file__), modname)
329 
330  if os.path.exists(moduledir):
331  print >> sys.stderr, "Module %r already exists" % (modname,)
332  return 2
333 
334  print "Creating module %r" % (modname,)
335 
336  os.mkdir(moduledir)
337  wscript = file(os.path.join(moduledir, "wscript"), "wt")
338  wscript.write(WSCRIPT_TEMPLATE % dict(MODULE=modname))
339  wscript.close()
340 
341 
342  #
343  # model
344  #
345  modeldir = os.path.join(moduledir, "model")
346  os.mkdir(modeldir)
347 
348  model_cc = file(os.path.join(moduledir, "model", "%s.cc" % modname), "wt")
349  model_cc.write(MODEL_CC_TEMPLATE % dict(MODULE=modname))
350  model_cc.close()
351 
352  model_h = file(os.path.join(moduledir, "model", "%s.h" % modname), "wt")
353  model_h.write(MODEL_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="%s_H" % (modname.replace("-", "_").upper()),))
354  model_h.close()
355 
356 
357 
358  #
359  # test
360  #
361  testdir = os.path.join(moduledir, "test")
362  os.mkdir(testdir)
363  test_cc = file(os.path.join(moduledir, "test", "%s-test-suite.cc" % modname), "wt")
364  test_cc.write(TEST_CC_TEMPLATE % dict(MODULE=modname,
365  CAPITALIZED=''.join([word.capitalize() for word in modname.split('-')]),
366  COMPOUND=''.join([modname.split('-')[0]] + [word.capitalize() for word in modname.split('-')[1:]]),
367  ))
368  test_cc.close()
369 
370 
371 
372  #
373  # helper
374  #
375  helperdir = os.path.join(moduledir, "helper")
376  os.mkdir(helperdir)
377 
378  helper_cc = file(os.path.join(moduledir, "helper", "%s-helper.cc" % modname), "wt")
379  helper_cc.write(HELPER_CC_TEMPLATE % dict(MODULE=modname))
380  helper_cc.close()
381 
382  helper_h = file(os.path.join(moduledir, "helper", "%s-helper.h" % modname), "wt")
383  helper_h.write(HELPER_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="%s_HELPER_H" % (modname.replace("-", "_").upper()),))
384  helper_h.close()
385 
386  #
387  # examples
388  #
389  examplesdir = os.path.join(moduledir, "examples")
390  os.mkdir(examplesdir)
391 
392  examples_wscript = file(os.path.join(examplesdir, "wscript"), "wt")
393  examples_wscript.write(EXAMPLES_WSCRIPT_TEMPLATE % dict(MODULE=modname))
394  examples_wscript.close()
395 
396  example_cc = file(os.path.join(moduledir, "examples", "%s-example.cc" % modname), "wt")
397  example_cc.write(EXAMPLE_CC_TEMPLATE % dict(MODULE=modname))
398  example_cc.close()
399 
400  #
401  # doc
402  #
403  docdir = os.path.join(moduledir, "doc")
404  os.mkdir(docdir)
405 
406  doc_rst = file(os.path.join(moduledir, "doc", "%s.rst" % modname), "wt")
407  doc_rst.write(DOC_RST_TEMPLATE % dict(MODULE=modname))
408  doc_rst.close()
409 
410 
411  return 0
412 
413 if __name__ == '__main__':
414  sys.exit(main(sys.argv))