A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
create-module.py
Go to the documentation of this file.
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 .. highlight:: cpp
219 
220 .. heading hierarchy:
221  ------------- Chapter
222  ************* Section (#.#)
223  ============= Subsection (#.#.#)
224  ############# Paragraph (no number)
225 
226 This is a suggested outline for adding new module documentation to |ns3|.
227 See ``src/click/doc/click.rst`` for an example.
228 
229 The introductory paragraph is for describing what this code is trying to
230 model.
231 
232 For consistency (italicized formatting), please use |ns3| to refer to
233 ns-3 in the documentation (and likewise, |ns2| for ns-2). These macros
234 are defined in the file ``replace.txt``.
235 
236 Model Description
237 *****************
238 
239 The source code for the new module lives in the directory ``src/%(MODULE)s``.
240 
241 Add here a basic description of what is being modeled.
242 
243 Design
244 ======
245 
246 Briefly describe the software design of the model and how it fits into
247 the existing ns-3 architecture.
248 
249 Scope and Limitations
250 =====================
251 
252 What can the model do? What can it not do? Please use this section to
253 describe the scope and limitations of the model.
254 
255 References
256 ==========
257 
258 Add academic citations here, such as if you published a paper on this
259 model, or if readers should read a particular specification or other work.
260 
261 Usage
262 *****
263 
264 This section is principally concerned with the usage of your model, using
265 the public API. Focus first on most common usage patterns, then go
266 into more advanced topics.
267 
268 Building New Module
269 ===================
270 
271 Include this subsection only if there are special build instructions or
272 platform limitations.
273 
274 Helpers
275 =======
276 
277 What helper API will users typically use? Describe it here.
278 
279 Attributes
280 ==========
281 
282 What classes hold attributes, and what are the key ones worth mentioning?
283 
284 Output
285 ======
286 
287 What kind of data does the model generate? What are the key trace
288 sources? What kind of logging output can be enabled?
289 
290 Advanced Usage
291 ==============
292 
293 Go into further details (such as using the API outside of the helpers)
294 in additional sections, as needed.
295 
296 Examples
297 ========
298 
299 What examples using this new code are available? Describe them here.
300 
301 Troubleshooting
302 ===============
303 
304 Add any tips for avoiding pitfalls, etc.
305 
306 Validation
307 **********
308 
309 Describe how the model has been tested/validated. What tests run in the
310 test suite? How much API and code is covered by the tests? Again,
311 references to outside published work may help here.
312 '''
313 
314 
315 def main(argv):
316  parser = OptionParser(usage=("Usage: %prog [options] modulename\n"
317  "Utility script to create a basic template for a new ns-3 module"))
318  (options, args) = parser.parse_args()
319  if len(args) != 1:
320  parser.print_help()
321  return 1
322 
323  modname = args[0].lower()
324  if False in [word.isalnum() for word in modname.split("-")]:
325  print >> sys.stderr, "Module name should only contain alphanumeric characters and dashes"
326  return 2
327  assert os.path.sep not in modname
328 
329  moduledir = os.path.join(os.path.dirname(__file__), modname)
330 
331  if os.path.exists(moduledir):
332  print >> sys.stderr, "Module %r already exists" % (modname,)
333  return 2
334 
335  print("Creating module %r, "
336  "run './waf configure' to include it in the build" % (modname,))
337 
338  os.mkdir(moduledir)
339  wscript = file(os.path.join(moduledir, "wscript"), "wt")
340  wscript.write(WSCRIPT_TEMPLATE % dict(MODULE=modname))
341  wscript.close()
342 
343 
344  #
345  # model
346  #
347  modeldir = os.path.join(moduledir, "model")
348  os.mkdir(modeldir)
349 
350  model_cc = file(os.path.join(moduledir, "model", "%s.cc" % modname), "wt")
351  model_cc.write(MODEL_CC_TEMPLATE % dict(MODULE=modname))
352  model_cc.close()
353 
354  model_h = file(os.path.join(moduledir, "model", "%s.h" % modname), "wt")
355  model_h.write(MODEL_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="%s_H" % (modname.replace("-", "_").upper()),))
356  model_h.close()
357 
358 
359 
360  #
361  # test
362  #
363  testdir = os.path.join(moduledir, "test")
364  os.mkdir(testdir)
365  test_cc = file(os.path.join(moduledir, "test", "%s-test-suite.cc" % modname), "wt")
366  test_cc.write(TEST_CC_TEMPLATE % dict(MODULE=modname,
367  CAPITALIZED=''.join([word.capitalize() for word in modname.split('-')]),
368  COMPOUND=''.join([modname.split('-')[0]] + [word.capitalize() for word in modname.split('-')[1:]]),
369  ))
370  test_cc.close()
371 
372 
373 
374  #
375  # helper
376  #
377  helperdir = os.path.join(moduledir, "helper")
378  os.mkdir(helperdir)
379 
380  helper_cc = file(os.path.join(moduledir, "helper", "%s-helper.cc" % modname), "wt")
381  helper_cc.write(HELPER_CC_TEMPLATE % dict(MODULE=modname))
382  helper_cc.close()
383 
384  helper_h = file(os.path.join(moduledir, "helper", "%s-helper.h" % modname), "wt")
385  helper_h.write(HELPER_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="%s_HELPER_H" % (modname.replace("-", "_").upper()),))
386  helper_h.close()
387 
388  #
389  # examples
390  #
391  examplesdir = os.path.join(moduledir, "examples")
392  os.mkdir(examplesdir)
393 
394  examples_wscript = file(os.path.join(examplesdir, "wscript"), "wt")
395  examples_wscript.write(EXAMPLES_WSCRIPT_TEMPLATE % dict(MODULE=modname))
396  examples_wscript.close()
397 
398  example_cc = file(os.path.join(moduledir, "examples", "%s-example.cc" % modname), "wt")
399  example_cc.write(EXAMPLE_CC_TEMPLATE % dict(MODULE=modname))
400  example_cc.close()
401 
402  #
403  # doc
404  #
405  docdir = os.path.join(moduledir, "doc")
406  os.mkdir(docdir)
407 
408  doc_rst = file(os.path.join(moduledir, "doc", "%s.rst" % modname), "wt")
409  doc_rst.write(DOC_RST_TEMPLATE % dict(MODULE=modname))
410  doc_rst.close()
411 
412 
413  return 0
414 
415 if __name__ == '__main__':
416  sys.exit(main(sys.argv))