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