10Test suite for the ns3 wrapper script
21from functools
import partial
24ns3_path = os.path.dirname(os.path.abspath(os.sep.join([__file__,
"../../"])))
25ns3_lock_filename = os.path.join(ns3_path,
".lock-ns3_%s_build" % sys.platform)
26ns3_script = os.sep.join([ns3_path,
"ns3"])
27ns3rc_script = os.sep.join([ns3_path,
".ns3rc"])
28usual_outdir = os.sep.join([ns3_path,
"build"])
29usual_lib_outdir = os.sep.join([usual_outdir,
"lib"])
35num_threads = max(1, os.cpu_count() - 1)
36cmake_build_project_command =
"cmake --build {cmake_cache} -j".format(
37 ns3_path=ns3_path, cmake_cache=os.path.abspath(os.path.join(ns3_path,
"cmake-cache"))
39cmake_build_target_command = partial(
40 "cmake --build {cmake_cache} -j {jobs} --target {target}".format,
42 cmake_cache=os.path.abspath(os.path.join(ns3_path,
"cmake-cache")),
44win32 = sys.platform ==
"win32"
45macos = sys.platform ==
"darwin"
46platform_makefiles =
"MinGW Makefiles" if win32
else "Unix Makefiles"
47ext =
".exe" if win32
else ""
48arch = platform.machine()
51def run_ns3(args, env=None, generator=platform_makefiles):
53 Runs the ns3 wrapper script with arguments
54 @param args: string containing arguments that will get split before calling ns3
55 @param env: environment variables dictionary
56 @param generator: CMake generator
57 @return tuple containing (error code, stdout and stderr)
61 possible_leftovers = [
"contrib/borked",
"contrib/calibre"]
62 for leftover
in possible_leftovers:
63 if os.path.exists(leftover):
64 shutil.rmtree(leftover, ignore_errors=
True)
66 args = args.format(generator=generator)
71 return run_program(ns3_script, args, python=
True, env=env)
75def run_program(program, args, python=False, cwd=ns3_path, env=None):
77 Runs a program with the given arguments and returns a tuple containing (error code, stdout and stderr)
78 @param program: program to execute (or python script)
79 @param args: string containing arguments that will get split before calling the program
80 @param python: flag indicating whether the program is a python script
81 @param cwd: the working directory used that will be the root folder for the execution
82 @param env: environment variables dictionary
83 @return tuple containing (error code, stdout and stderr)
86 raise Exception(
"args should be a string")
90 arguments = [sys.executable, program]
95 arguments.extend(re.findall(
r'(?:".*?"|\S)+', args))
97 for i
in range(len(arguments)):
98 arguments[i] = arguments[i].replace(
'"',
"")
101 current_env = os.environ.copy()
105 current_env.update(env)
108 ret = subprocess.run(
110 stdin=subprocess.DEVNULL,
111 stdout=subprocess.PIPE,
112 stderr=subprocess.PIPE,
119 ret.stdout.decode(sys.stdout.encoding),
120 ret.stderr.decode(sys.stderr.encoding),
126 Extracts the programs list from .lock-ns3
127 @return list of programs.
130 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
131 exec(f.read(), globals(), values)
133 programs_list = values[
"ns3_runnable_programs"]
137 programs_list = list(map(
lambda x: x + ext, programs_list))
143 Gets a list of built libraries
144 @param lib_outdir: path containing libraries
145 @return list of built libraries.
147 if not os.path.exists(lib_outdir):
149 libraries = glob.glob(lib_outdir +
"/*", recursive=
True)
150 return list(filter(
lambda x:
"scratch-nested-subdir-lib" not in x, libraries))
155 Gets a list of header files
156 @param outdir: path containing headers
157 @return list of headers.
159 return glob.glob(outdir +
"/**/*.h", recursive=
True)
164 Read interesting entries from the .lock-ns3 file
165 @param entry: entry to read from .lock-ns3
166 @return value of the requested entry.
169 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
170 exec(f.read(), globals(), values)
171 return values.get(entry,
None)
176 Check if tests are enabled in the .lock-ns3
184 Check if tests are enabled in the .lock-ns3
185 @return list of enabled modules (prefixed with 'ns3-').
192 Python-on-whales wrapper for Docker-based ns-3 tests
195 def __init__(self, currentTestCase: unittest.TestCase, containerName: str =
"ubuntu:latest"):
197 Create and start container with containerName in the current ns-3 directory
198 @param self: the current DockerContainerManager instance
199 @param currentTestCase: the test case instance creating the DockerContainerManager
200 @param containerName: name of the container image to be used
202 global DockerException
204 from python_on_whales
import docker
205 from python_on_whales.exceptions
import DockerException
206 except ModuleNotFoundError:
208 DockerException =
None
209 currentTestCase.skipTest(
"python-on-whales was not found")
212 with open(os.path.expanduser(
"~/.bashrc"),
"r", encoding=
"utf-8")
as f:
213 docker_settings = re.findall(
"(DOCKER_.*=.*)", f.read())
215 for setting
in docker_settings:
216 key, value = setting.split(
"=")
217 os.environ[key] = value
218 del setting, key, value
223 except DockerException
as e:
224 currentTestCase.skipTest(f
"python-on-whales returned:{e.__str__()}")
233 volumes=[(ns3_path,
"/ns-3-dev")],
237 def split_exec(docker_container, cmd, workdir="/ns-3-dev"):
238 cmd_split = re.findall(
r'(?:".*?"|\S)+', cmd)
239 cmd_split = list(map(
lambda x: x.replace(
'"',
""), cmd_split))
240 return docker_container._execute(cmd_split, workdir=workdir)
247 Return the managed container when entiring the block "with DockerContainerManager() as container"
248 @param self: the current DockerContainerManager instance
249 @return container managed by DockerContainerManager.
255 Clean up the managed container at the end of the block "with DockerContainerManager() as container"
256 @param self: the current DockerContainerManager instance
257 @param exc_type: unused parameter
258 @param exc_val: unused parameter
259 @param exc_tb: unused parameter
268 ns-3 tests related to checking if source files were left behind, not being used by CMake
272 directory_and_files = {}
276 Scan all C++ source files and add them to a list based on their path
279 for root, dirs, files
in os.walk(ns3_path):
280 if "gitlab-ci-local" in root:
283 if name.endswith(
".cc"):
284 path = os.path.join(root, name)
285 directory = os.path.dirname(path)
292 Test if all example source files are being used in their respective CMakeLists.txt
295 unused_sources = set()
298 if os.sep +
"examples" not in example_directory:
302 if not os.path.exists(os.path.join(example_directory,
"CMakeLists.txt")):
307 os.path.join(example_directory,
"CMakeLists.txt"),
"r", encoding=
"utf-8"
309 cmake_contents = f.read()
314 if os.path.basename(file).replace(
".cc",
"")
not in cmake_contents:
315 unused_sources.add(file)
317 self.assertListEqual([], list(unused_sources))
321 Test if all module source files are being used in their respective CMakeLists.txt
324 unused_sources = set()
327 is_not_module =
not (
"src" in directory
or "contrib" in directory)
328 is_example = os.sep +
"examples" in directory
329 is_bindings = os.sep +
"bindings" in directory
331 if is_not_module
or is_bindings
or is_example:
336 cmake_path = os.path.join(directory,
"CMakeLists.txt")
337 while not os.path.exists(cmake_path):
338 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
339 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
342 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
343 cmake_contents = f.read()
347 if os.path.basename(file)
not in cmake_contents:
348 unused_sources.add(file)
352 "win32-system-wall-clock-ms.cc",
354 for exception
in exceptions:
355 for unused_source
in unused_sources:
356 if os.path.basename(unused_source) == exception:
357 unused_sources.remove(unused_source)
360 self.assertListEqual([], list(unused_sources))
364 Test if all utils source files are being used in their respective CMakeLists.txt
367 unused_sources = set()
370 is_module =
"src" in directory
or "contrib" in directory
371 if os.sep +
"utils" not in directory
or is_module:
376 cmake_path = os.path.join(directory,
"CMakeLists.txt")
377 while not os.path.exists(cmake_path):
378 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
379 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
382 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
383 cmake_contents = f.read()
387 if os.path.basename(file)
not in cmake_contents:
388 unused_sources.add(file)
390 self.assertListEqual([], list(unused_sources))
395 ns-3 tests related to dependencies
400 Checks if headers from different modules (src/A, contrib/B) that are included by
401 the current module (src/C) source files correspond to the list of linked modules
403 LIBRARIES_TO_LINK A (missing B)
407 headers_to_modules = {}
408 module_paths = glob.glob(ns3_path +
"/src/*/") + glob.glob(ns3_path +
"/contrib/*/")
410 for path
in module_paths:
412 cmake_path = os.path.join(path,
"CMakeLists.txt")
413 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
414 cmake_contents = f.readlines()
416 module_name = os.path.relpath(path, ns3_path)
417 module_name_nodir = module_name.replace(
"src/",
"").replace(
"contrib/",
"")
418 modules[module_name_nodir] = {
422 "included_headers": set(),
423 "included_libraries": set(),
427 for line
in cmake_contents:
428 source_file_path = re.findall(
r"\b(?:[^\s]+\.[ch]{1,2})\b", line.strip())
429 if not source_file_path:
431 source_file_path = source_file_path[0]
432 base_name = os.path.basename(source_file_path)
433 if not os.path.exists(os.path.join(path, source_file_path)):
436 if ".h" in source_file_path:
438 modules[module_name_nodir][
"headers"].add(base_name)
439 modules[module_name_nodir][
"sources"].add(base_name)
442 headers_to_modules[base_name] = module_name_nodir
444 if ".cc" in source_file_path:
446 modules[module_name_nodir][
"sources"].add(base_name)
448 if ".cc" in source_file_path
or ".h" in source_file_path:
450 source_file = os.path.join(ns3_path, module_name, source_file_path)
451 with open(source_file,
"r", encoding=
"utf-8")
as f:
452 source_contents = f.read()
453 modules[module_name_nodir][
"included_headers"].update(
455 lambda x: x.replace(
"ns3/",
""),
456 re.findall(
'#include.*["|<](.*)["|>]', source_contents),
462 modules[module_name_nodir][
"libraries"].update(
463 re.findall(
r"\${lib(.*?)}",
"".join(cmake_contents))
465 modules[module_name_nodir][
"libraries"] = list(
468 not in [
"raries_to_link", module_name_nodir, module_name_nodir +
"-obj"],
469 modules[module_name_nodir][
"libraries"],
474 all_project_headers = set(headers_to_modules.keys())
477 print(file=sys.stderr)
478 for module
in sorted(modules):
479 external_headers = modules[module][
"included_headers"].difference(all_project_headers)
480 project_headers_included = modules[module][
"included_headers"].difference(
483 modules[module][
"included_libraries"] = set(
484 [headers_to_modules[x]
for x
in project_headers_included]
485 ).difference({module})
487 diff = modules[module][
"included_libraries"].difference(modules[module][
"libraries"])
490 def recursive_check_dependencies(checked_module):
492 for module_to_link
in modules[checked_module][
"included_libraries"]:
493 modules[checked_module][
"included_libraries"] = set(
494 modules[checked_module][
"included_libraries"]
495 ) - set(modules[module_to_link][
"included_libraries"])
497 for module_to_link
in modules[checked_module][
"included_libraries"]:
498 recursive_check_dependencies(module_to_link)
501 def is_implicitly_linked(searched_module, current_module):
502 if len(modules[current_module][
"included_libraries"]) == 0:
504 if searched_module
in modules[current_module][
"included_libraries"]:
506 for module
in modules[current_module][
"included_libraries"]:
507 if is_implicitly_linked(searched_module, module):
511 from itertools
import combinations
513 implicitly_linked = set()
514 for dep1, dep2
in combinations(modules[checked_module][
"included_libraries"], 2):
515 if is_implicitly_linked(dep1, dep2):
516 implicitly_linked.add(dep1)
517 if is_implicitly_linked(dep2, dep1):
518 implicitly_linked.add(dep2)
520 modules[checked_module][
"included_libraries"] = (
521 set(modules[checked_module][
"included_libraries"]) - implicitly_linked
524 for module
in modules:
525 recursive_check_dependencies(module)
528 for module
in sorted(modules):
531 minimal_linking_set =
", ".join(modules[module][
"included_libraries"])
532 unnecessarily_linked =
", ".join(
533 set(modules[module][
"libraries"]) - set(modules[module][
"included_libraries"])
535 missing_linked =
", ".join(
536 set(modules[module][
"included_libraries"]) - set(modules[module][
"libraries"])
538 if unnecessarily_linked:
539 print(f
"Module '{module}' unnecessarily linked: {unnecessarily_linked}.")
541 print(f
"Module '{module}' missing linked: {missing_linked}.")
542 if unnecessarily_linked
or missing_linked:
543 print(f
"Module '{module}' minimal linking set: {minimal_linking_set}.")
544 self.assertTrue(
True)
549 ns-3 tests to check if the source code, whitespaces and CMake formatting
550 are according to the coding style
560 Import GitRepo and load the original diff state of the repository before the tests
563 if not NS3StyleTestCase.starting_diff:
564 if shutil.which(
"git")
is None:
565 self.skipTest(
"Git is not available")
571 self.skipTest(
"GitPython is not available")
574 repo = Repo(ns3_path)
575 except git.exc.InvalidGitRepositoryError:
576 self.skipTest(
"ns-3 directory does not contain a .git directory")
578 hcommit = repo.head.commit
579 NS3StyleTestCase.starting_diff = hcommit.diff(
None)
580 NS3StyleTestCase.repo = repo
582 if NS3StyleTestCase.starting_diff
is None:
583 self.skipTest(
"Unmet dependencies")
587 Check if there is any difference between tracked file after
588 applying cmake-format
592 for required_program
in [
"cmake",
"cmake-format"]:
593 if shutil.which(required_program)
is None:
594 self.skipTest(
"%s was not found" % required_program)
597 return_code, stdout, stderr =
run_ns3(
"configure")
598 self.assertEqual(return_code, 0)
601 return_code, stdout, stderr =
run_ns3(
"build cmake-format")
602 self.assertEqual(return_code, 0)
605 return_code, stdout, stderr =
run_ns3(
"clean")
606 self.assertEqual(return_code, 0)
609 new_diff = NS3StyleTestCase.repo.head.commit.diff(
None)
610 self.assertEqual(NS3StyleTestCase.starting_diff, new_diff)
615 ns3 tests related to generic options
620 Clean configuration/build artifacts before common commands
629 Test not passing any arguments to
632 return_code, stdout, stderr =
run_ns3(
"")
633 self.assertEqual(return_code, 1)
634 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
638 Test only passing --quiet argument to ns3
641 return_code, stdout, stderr =
run_ns3(
"--quiet")
642 self.assertEqual(return_code, 1)
643 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
647 Test only passing 'show config' argument to ns3
650 return_code, stdout, stderr =
run_ns3(
"show config")
651 self.assertEqual(return_code, 1)
652 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
656 Test only passing 'show profile' argument to ns3
659 return_code, stdout, stderr =
run_ns3(
"show profile")
660 self.assertEqual(return_code, 1)
661 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
665 Test only passing 'show version' argument to ns3
668 return_code, stdout, stderr =
run_ns3(
"show version")
669 self.assertEqual(return_code, 1)
670 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
675 ns3 tests related to build profiles
680 Clean configuration/build artifacts before testing configuration settings
692 return_code, stdout, stderr =
run_ns3(
693 'configure -G "{generator}" -d debug --enable-verbose'
695 self.assertEqual(return_code, 0)
696 self.assertIn(
"Build profile : debug", stdout)
697 self.assertIn(
"Build files have been written to", stdout)
700 return_code, stdout, stderr =
run_ns3(
"build core")
701 self.assertEqual(return_code, 0)
702 self.assertIn(
"Built target core", stdout)
705 self.assertGreater(len(libraries), 0)
706 self.assertIn(
"core-debug", libraries[0])
710 Test the release build
713 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d release')
714 self.assertEqual(return_code, 0)
715 self.assertIn(
"Build profile : release", stdout)
716 self.assertIn(
"Build files have been written to", stdout)
720 Test the optimized build
723 return_code, stdout, stderr =
run_ns3(
724 'configure -G "{generator}" -d optimized --enable-verbose'
726 self.assertEqual(return_code, 0)
727 self.assertIn(
"Build profile : optimized", stdout)
728 self.assertIn(
"Build files have been written to", stdout)
731 return_code, stdout, stderr =
run_ns3(
"build core")
732 self.assertEqual(return_code, 0)
733 self.assertIn(
"Built target core", stdout)
736 self.assertGreater(len(libraries), 0)
737 self.assertIn(
"core-optimized", libraries[0])
741 Test a build type with a typo
744 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d Optimized')
745 self.assertEqual(return_code, 2)
746 self.assertIn(
"invalid choice: 'Optimized'", stderr)
750 Test a build type with another typo
753 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d OPTIMIZED')
754 self.assertEqual(return_code, 2)
755 self.assertIn(
"invalid choice: 'OPTIMIZED'", stderr)
759 Replace settings set by default (e.g. ASSERT/LOGs enabled in debug builds and disabled in default ones)
762 return_code, _, _ =
run_ns3(
"clean")
763 self.assertEqual(return_code, 0)
765 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run -d debug')
766 self.assertEqual(return_code, 0)
768 "-DCMAKE_BUILD_TYPE=debug -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON -DNS3_NATIVE_OPTIMIZATIONS=OFF",
772 return_code, stdout, stderr =
run_ns3(
773 'configure -G "{generator}" --dry-run -d debug --disable-asserts --disable-logs --disable-werror'
775 self.assertEqual(return_code, 0)
777 "-DCMAKE_BUILD_TYPE=debug -DNS3_NATIVE_OPTIMIZATIONS=OFF -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF",
781 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run')
782 self.assertEqual(return_code, 0)
784 "-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF -DNS3_NATIVE_OPTIMIZATIONS=OFF",
788 return_code, stdout, stderr =
run_ns3(
789 'configure -G "{generator}" --dry-run --enable-asserts --enable-logs --enable-werror'
791 self.assertEqual(return_code, 0)
793 "-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_NATIVE_OPTIMIZATIONS=OFF -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON",
800 Generic test case with basic function inherited by more complex tests.
805 Check if configuration for release mode worked normally
806 @param return_code: return code from CMake
807 @param stdout: output from CMake.
808 @param stderr: error from CMake.
811 self.assertEqual(return_code, 0)
812 self.assertIn(
"Build profile : release", stdout)
813 self.assertIn(
"Build files have been written to", stdout)
814 self.assertNotIn(
"uninitialized variable", stderr)
818 Clean configuration/build artifacts before testing configuration and build settings
819 After configuring the build as release,
820 check if configuration worked and check expected output files.
825 if os.path.exists(ns3rc_script):
826 os.remove(ns3rc_script)
830 return_code, stdout, stderr =
run_ns3(
831 'configure -G "{generator}" -d release --enable-verbose'
833 self.
config_ok(return_code, stdout, stderr)
836 self.assertTrue(os.path.exists(ns3_lock_filename))
841 self.assertTrue(os.path.exists(ns3_lock_filename))
848 Test ns3 configuration options
853 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
860 Test enabling and disabling examples
863 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
866 self.
config_ok(return_code, stdout, stderr)
873 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
876 self.
config_ok(return_code, stdout, stderr)
883 Test enabling and disabling tests
887 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-tests')
888 self.
config_ok(return_code, stdout, stderr)
891 return_code, stdout, stderr =
run_ns3(
"build core-test")
894 self.assertEqual(return_code, 0)
895 self.assertIn(
"Built target core-test", stdout)
898 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-tests')
899 self.
config_ok(return_code, stdout, stderr)
902 return_code, stdout, stderr =
run_ns3(
"build core-test")
905 self.assertEqual(return_code, 1)
906 self.assertIn(
"Target to build does not exist: core-test", stdout)
910 Test enabling specific modules
914 return_code, stdout, stderr =
run_ns3(
915 "configure -G \"{generator}\" --enable-modules='network;wifi'"
917 self.
config_ok(return_code, stdout, stderr)
923 self.assertIn(
"ns3-network", enabled_modules)
924 self.assertIn(
"ns3-wifi", enabled_modules)
927 return_code, stdout, stderr =
run_ns3(
928 "configure -G \"{generator}\" --enable-modules='core'"
930 self.
config_ok(return_code, stdout, stderr)
934 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
935 self.
config_ok(return_code, stdout, stderr)
942 Test disabling specific modules
946 return_code, stdout, stderr =
run_ns3(
947 "configure -G \"{generator}\" --disable-modules='lte;wifi'"
949 self.
config_ok(return_code, stdout, stderr)
953 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
954 self.assertNotIn(
"ns3-lte", enabled_modules)
955 self.assertNotIn(
"ns3-wifi", enabled_modules)
958 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
959 self.
config_ok(return_code, stdout, stderr)
966 Test enabling comma-separated (waf-style) examples
970 return_code, stdout, stderr =
run_ns3(
971 "configure -G \"{generator}\" --enable-modules='network,wifi'"
973 self.
config_ok(return_code, stdout, stderr)
978 self.assertIn(
"ns3-network", enabled_modules)
979 self.assertIn(
"ns3-wifi", enabled_modules)
982 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
983 self.
config_ok(return_code, stdout, stderr)
990 Test disabling comma-separated (waf-style) examples
994 return_code, stdout, stderr =
run_ns3(
995 "configure -G \"{generator}\" --disable-modules='lte,mpi'"
997 self.
config_ok(return_code, stdout, stderr)
1001 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
1002 self.assertNotIn(
"ns3-lte", enabled_modules)
1003 self.assertNotIn(
"ns3-mpi", enabled_modules)
1006 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
1007 self.
config_ok(return_code, stdout, stderr)
1014 Test loading settings from the ns3rc config file
1020 ns3rc_python_template =
"# ! /usr/bin/env python\
1022 # A list of the modules that will be enabled when ns-3 is run.\
1023 # Modules that depend on the listed modules will be enabled also.\
1025 # All modules can be enabled by choosing 'all_modules'.\
1026 modules_enabled = [{modules}]\
1028 # Set this equal to true if you want examples to be run.\
1029 examples_enabled = {examples}\
1031 # Set this equal to true if you want tests to be run.\
1032 tests_enabled = {tests}\
1036 ns3rc_cmake_template =
"set(ns3rc_tests_enabled {tests})\
1037 \nset(ns3rc_examples_enabled {examples})\
1038 \nset(ns3rc_enabled_modules {modules})\
1042 ns3rc_templates = {
"python": ns3rc_python_template,
"cmake": ns3rc_cmake_template}
1044 def __init__(self, type_ns3rc):
1048 def format(self, **args):
1050 if self.
type ==
"cmake":
1052 args[
"modules"].replace(
"'",
"").replace(
'"',
"").replace(
",",
" ")
1054 args[
"examples"] =
"ON" if args[
"examples"] ==
"True" else "OFF"
1055 args[
"tests"] =
"ON" if args[
"tests"] ==
"True" else "OFF"
1057 formatted_string = ns3rc_str.ns3rc_templates[self.
type].format(**args)
1060 return formatted_string
1064 return ns3rc_str.ns3rc_templates.keys()
1066 for ns3rc_type
in ns3rc_str.types():
1068 ns3rc_template = ns3rc_str(ns3rc_type)
1071 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1072 f.write(ns3rc_template.format(modules=
"'lte'", examples=
"False", tests=
"True"))
1076 return_code, stdout, stderr =
run_ns3(
1077 'configure -G "{generator}" -d release --enable-verbose'
1079 self.
config_ok(return_code, stdout, stderr)
1084 self.assertIn(
"ns3-lte", enabled_modules)
1086 self.assertLessEqual(
1091 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1092 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
1095 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1096 self.
config_ok(return_code, stdout, stderr)
1101 self.assertIn(
"ns3-wifi", enabled_modules)
1106 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1108 ns3rc_template.format(
1109 modules=
"'core','network'", examples=
"True", tests=
"False"
1114 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1115 self.
config_ok(return_code, stdout, stderr)
1120 self.assertIn(
"ns3-core", enabled_modules)
1121 self.assertIn(
"ns3-network", enabled_modules)
1127 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1128 if ns3rc_type ==
"python":
1130 ns3rc_template.format(
1131 modules=
"""'core', #comment
1135 'network', 'internet','wifi'""",
1142 ns3rc_template.format(
1143 modules=
"'core', 'lte', 'network', 'internet', 'wifi'",
1149 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1150 self.
config_ok(return_code, stdout, stderr)
1155 self.assertIn(
"ns3-core", enabled_modules)
1156 self.assertIn(
"ns3-internet", enabled_modules)
1157 self.assertIn(
"ns3-lte", enabled_modules)
1158 self.assertIn(
"ns3-wifi", enabled_modules)
1163 os.remove(ns3rc_script)
1166 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1167 self.
config_ok(return_code, stdout, stderr)
1176 Test dry-run (printing commands to be executed instead of running them)
1182 for positional_command
in [
"configure",
"build",
"clean"]:
1183 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
1184 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
1186 self.assertEqual(return_code, return_code1)
1187 self.assertEqual(stdout, stdout1)
1188 self.assertEqual(stderr, stderr1)
1193 run_ns3(
'configure -G "{generator}" -d release --enable-verbose')
1194 run_ns3(
"build scratch-simulator")
1197 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
1198 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
1199 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
1200 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
1203 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
1204 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
1208 if "scratch-simulator" in program
and "subdir" not in program:
1209 scratch_path = program
1215 self.assertIn(scratch_path, stdout0)
1219 self.assertIn(
"Built target", stdout1)
1220 self.assertNotIn(scratch_path, stdout1)
1223 self.assertIn(
"The following commands would be executed:", stdout2)
1224 self.assertIn(scratch_path, stdout2)
1227 self.assertNotIn(
"Finished executing the following commands:", stdout3)
1228 self.assertNotIn(scratch_path, stdout3)
1232 Test if ns3 is propagating back the return code from the executables called with the run command
1236 return_code, _, _ =
run_ns3(
"clean")
1237 self.assertEqual(return_code, 0)
1239 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-examples --enable-tests')
1240 self.assertEqual(return_code, 0)
1243 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
1244 self.assertEqual(return_code, 0)
1247 return_code, stdout, stderr =
run_ns3(
1248 'run "test-runner --test-name=command-line" --no-build'
1250 self.assertEqual(return_code, 0)
1253 return_code, stdout, stderr =
run_ns3(
1254 'run "test-runner --test-name=command-line" --no-build',
1255 env={
"NS_COMMANDLINE_INTROSPECTION":
".."},
1257 self.assertNotEqual(return_code, 0)
1260 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
1261 with open(sigsegv_example,
"w", encoding=
"utf-8")
as f:
1263 int main (int argc, char *argv[])
1265 char *s = "hello world"; *s = 'H';
1269 return_code, stdout, stderr =
run_ns3(
"run sigsegv")
1271 self.assertEqual(return_code, 4294967295)
1272 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1274 self.assertEqual(return_code, 245)
1275 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1278 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1279 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1281 #include "ns3/core-module.h"
1283 using namespace ns3;
1284 int main (int argc, char *argv[])
1290 return_code, stdout, stderr =
run_ns3(
"run abort")
1292 self.assertNotEqual(return_code, 0)
1293 self.assertIn(
"abort-default.exe' returned non-zero exit status", stdout)
1295 self.assertEqual(return_code, 250)
1296 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
1298 os.remove(sigsegv_example)
1299 os.remove(abort_example)
1303 Test passing 'show config' argument to ns3 to get the configuration table
1306 return_code, stdout, stderr =
run_ns3(
"show config")
1307 self.assertEqual(return_code, 0)
1308 self.assertIn(
"Summary of ns-3 settings", stdout)
1312 Test passing 'show profile' argument to ns3 to get the build profile
1315 return_code, stdout, stderr =
run_ns3(
"show profile")
1316 self.assertEqual(return_code, 0)
1317 self.assertIn(
"Build profile: release", stdout)
1321 Test passing 'show version' argument to ns3 to get the build version
1324 if shutil.which(
"git")
is None:
1325 self.skipTest(
"git is not available")
1327 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-build-version')
1328 self.assertEqual(return_code, 0)
1330 return_code, stdout, stderr =
run_ns3(
"show version")
1331 self.assertEqual(return_code, 0)
1332 self.assertIn(
"ns-3 version:", stdout)
1336 Test if CMake target names for scratches and ns3 shortcuts
1337 are working correctly
1344 "scratch/subdir1/main.cc",
1345 "scratch/subdir2/main.cc",
1346 "scratch/main.test.dots.in.name.cc",
1348 backup_files = [
"scratch/.main.cc"]
1351 for path
in test_files + backup_files:
1352 filepath = os.path.join(ns3_path, path)
1353 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
1354 with open(filepath,
"w", encoding=
"utf-8")
as f:
1356 f.write(
"int main (int argc, char *argv[]){}")
1365 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1366 self.assertEqual(return_code, 1)
1369 empty =
"scratch/empty.cc"
1371 test_files.remove(empty)
1372 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1373 self.assertEqual(return_code, 0)
1376 for path
in test_files + backup_files:
1377 path = path.replace(
".cc",
"")
1380 "--build . --target %s -j %d" % (path.replace(
"/",
"_"), num_threads),
1381 cwd=os.path.join(ns3_path,
"cmake-cache"),
1383 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
1384 if "main" in path
and ".main" not in path:
1385 self.assertEqual(return_code1, 0)
1386 self.assertEqual(return_code2, 0)
1388 self.assertEqual(return_code1, 2)
1389 self.assertEqual(return_code2, 1)
1392 for path
in test_files:
1393 path = path.replace(
".cc",
"")
1394 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
1396 self.assertEqual(return_code, 0)
1398 self.assertEqual(return_code, 1)
1402 container.execute(
"apt-get update")
1403 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
1406 "./ns3 configure --enable-modules=core,network,internet -- -DCMAKE_CXX_COMPILER=/usr/bin/g++"
1408 except DockerException
as e:
1410 for path
in test_files:
1411 path = path.replace(
".cc",
"")
1413 container.execute(f
"./ns3 run {path}")
1414 except DockerException
as e:
1420 for path
in test_files + backup_files:
1421 source_absolute_path = os.path.join(ns3_path, path)
1422 os.remove(source_absolute_path)
1423 if "empty" in path
or ".main" in path:
1425 filename = os.path.basename(path).replace(
".cc",
"")
1426 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
1427 if os.path.exists(executable_absolute_path):
1428 executable_name = list(
1429 filter(
lambda x: filename
in x, os.listdir(executable_absolute_path))
1432 os.remove(os.path.join(executable_absolute_path, executable_name))
1433 if not os.listdir(os.path.dirname(path)):
1434 os.rmdir(os.path.dirname(source_absolute_path))
1436 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1437 self.assertEqual(return_code, 0)
1441 Test if ns3 is inserting additional arguments by MPICH and OpenMPI to run on the CI
1445 if shutil.which(
"mpiexec")
is None or win32:
1446 self.skipTest(
"Mpi is not available")
1448 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1449 self.assertEqual(return_code, 0)
1453 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
1454 self.assertEqual(return_code, 0)
1457 sample_simulator_path = list(filter(
lambda x:
"sample-simulator" in x, executables))[0]
1459 mpi_command =
'--dry-run run sample-simulator --command-template="mpiexec -np 2 %s"'
1460 non_mpi_command =
'--dry-run run sample-simulator --command-template="echo %s"'
1463 return_code, stdout, stderr =
run_ns3(mpi_command)
1464 self.assertEqual(return_code, 0)
1465 self.assertIn(
'mpiexec -np 2 "%s"' % sample_simulator_path, stdout)
1468 return_code, stdout, stderr =
run_ns3(mpi_command)
1469 self.assertEqual(return_code, 0)
1470 if os.getenv(
"USER",
"") ==
"root":
1471 if shutil.which(
"ompi_info"):
1473 'mpiexec --allow-run-as-root --oversubscribe -np 2 "%s"'
1474 % sample_simulator_path,
1479 'mpiexec --allow-run-as-root -np 2 "%s"' % sample_simulator_path, stdout
1482 self.assertIn(
'mpiexec -np 2 "%s"' % sample_simulator_path, stdout)
1485 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1486 self.assertEqual(return_code, 0)
1487 self.assertIn(
'echo "%s"' % sample_simulator_path, stdout)
1490 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1491 self.assertEqual(return_code, 0)
1492 self.assertIn(
'echo "%s"' % sample_simulator_path, stdout)
1494 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1495 self.assertEqual(return_code, 0)
1499 Test if CMake and ns3 fail in the expected ways when:
1500 - examples from modules or general examples fail if they depend on a
1501 library with a name shorter than 4 characters or are disabled when
1502 a library is nonexistent
1503 - a module library passes the configuration but fails to build due to
1507 os.makedirs(
"contrib/borked", exist_ok=
True)
1508 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1511 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1513 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1514 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1518 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1519 LIBRARIES_TO_LINK ${libcore} %s
1521 """ % invalid_or_nonexistent_library)
1523 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1524 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1525 self.assertEqual(return_code, 0)
1526 elif invalid_or_nonexistent_library
in [
"lib"]:
1527 self.assertEqual(return_code, 1)
1528 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1532 return_code, stdout, stderr =
run_ns3(
"build borked")
1533 if invalid_or_nonexistent_library
in [
""]:
1534 self.assertEqual(return_code, 0)
1535 elif invalid_or_nonexistent_library
in [
"lib"]:
1536 self.assertEqual(return_code, 2)
1537 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1538 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1539 self.assertEqual(return_code, 2)
1540 if "lld" in stdout + stderr:
1542 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1544 elif "mold" in stdout + stderr:
1545 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1548 "library not found for -l%s" % invalid_or_nonexistent_library, stderr
1551 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1559 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1563 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1564 LIBRARIES_TO_LINK ${libcore}
1567 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1568 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1572 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1573 LIBRARIES_TO_LINK ${libborked} %s
1575 """ % invalid_or_nonexistent_library)
1577 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1578 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1579 self.assertEqual(return_code, 0)
1580 elif invalid_or_nonexistent_library
in [
"lib"]:
1581 self.assertEqual(return_code, 1)
1582 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1586 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1587 if invalid_or_nonexistent_library
in [
""]:
1588 self.assertEqual(return_code, 0)
1589 elif invalid_or_nonexistent_library
in [
"libf"]:
1590 self.assertEqual(return_code, 2)
1591 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1592 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1593 self.assertEqual(return_code, 1)
1594 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1598 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1602 Test if CMake can properly handle modules containing "lib",
1603 which is used internally as a prefix for module libraries
1607 os.makedirs(
"contrib/calibre", exist_ok=
True)
1608 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1611 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1613 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1617 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1618 LIBRARIES_TO_LINK ${libcore}
1622 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1625 self.assertEqual(return_code, 0)
1628 self.assertIn(
"calibre", stdout)
1632 self.assertNotIn(
"care", stdout)
1634 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1638 return_code, stdout, stderr =
run_ns3(
"build calibre")
1639 self.assertEqual(return_code, 0)
1642 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1646 Test if CMake performance tracing works and produces the
1647 cmake_performance_trace.log file
1650 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1651 if os.path.exists(cmake_performance_trace_log):
1652 os.remove(cmake_performance_trace_log)
1654 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1655 self.assertEqual(return_code, 0)
1657 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1660 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1663 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1667 Check if ENABLE_BUILD_VERSION and version.cache are working
1675 container.execute(
"apt-get update")
1676 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1679 container.execute(
"./ns3 clean")
1682 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1685 if os.path.exists(version_cache_file):
1686 os.remove(version_cache_file)
1690 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1691 except DockerException:
1693 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1696 version_cache_contents = (
1697 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1698 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1699 "VERSION_DIRTY_FLAG = '0'\n"
1700 "VERSION_MAJOR = '3'\n"
1701 "VERSION_MINOR = '0'\n"
1702 "VERSION_PATCH = '0'\n"
1703 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1704 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1705 "VERSION_TAG_DISTANCE = '0'\n"
1706 "VERSION_BUILD_PROFILE = 'debug'\n"
1708 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1709 version.write(version_cache_contents)
1712 container.execute(
"./ns3 clean")
1713 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1714 container.execute(
"./ns3 build core")
1715 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1718 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1719 self.assertEqual(version.read(), version_cache_contents)
1724 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1726 container.execute(
"apt-get install -y git")
1727 container.execute(
"./ns3 clean")
1728 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1729 container.execute(
"./ns3 build core")
1730 except DockerException:
1732 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1733 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1736 container.execute(
"./ns3 clean")
1737 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1738 container.execute(
"./ns3 build core")
1739 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1740 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1741 self.assertNotEqual(version.read(), version_cache_contents)
1744 if os.path.exists(version_cache_file):
1745 os.remove(version_cache_file)
1749 Test filtering in examples and tests from specific modules
1753 return_code, stdout, stderr =
run_ns3(
1754 'configure -G "{generator}" --enable-examples --enable-tests'
1756 self.
config_ok(return_code, stdout, stderr)
1761 return_code, stdout, stderr =
run_ns3(
1762 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1764 self.
config_ok(return_code, stdout, stderr)
1770 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1772 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1775 return_code, stdout, stderr =
run_ns3(
1776 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1778 self.
config_ok(return_code, stdout, stderr)
1786 return_code, stdout, stderr =
run_ns3(
1787 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1789 self.
config_ok(return_code, stdout, stderr)
1797 Check if fast linkers LLD and Mold are correctly found and configured
1804 container.execute(
"apt-get update")
1805 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1808 container.execute(
"./ns3 configure -G Ninja")
1811 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1813 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1815 self.assertIn(
"-fuse-ld=lld", f.read())
1819 container.execute(
"./ns3 build core")
1820 except DockerException:
1821 self.assertTrue(
False,
"Build with lld failed")
1824 if not os.path.exists(f
"./mold-1.4.2-{arch}-linux.tar.gz"):
1826 f
"wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch}-linux.tar.gz"
1829 f
"tar xzfC mold-1.4.2-{arch}-linux.tar.gz /usr/local --strip-components=1"
1834 container.execute(
"./ns3 configure -G Ninja")
1837 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1839 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1841 self.assertIn(
"-fuse-ld=mold", f.read())
1845 container.execute(
"./ns3 build core")
1846 except DockerException:
1847 self.assertTrue(
False,
"Build with mold failed")
1850 os.remove(f
"./mold-1.4.2-{arch}-linux.tar.gz")
1853 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1856 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1858 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1860 self.assertNotIn(
"-fuse-ld=mold", f.read())
1864 Check if NS3_CLANG_TIMETRACE feature is working
1865 Clang's -ftime-trace plus ClangAnalyzer report
1871 container.execute(
"apt-get update")
1872 container.execute(
"apt-get install -y python3 ninja-build cmake clang-18")
1877 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1879 except DockerException
as e:
1880 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1882 container.execute(
"apt-get install -y git")
1887 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1889 except DockerException
as e:
1890 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1893 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1894 if os.path.exists(time_trace_report_path):
1895 os.remove(time_trace_report_path)
1899 container.execute(
"./ns3 build timeTraceReport")
1900 except DockerException
as e:
1901 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1904 self.assertTrue(os.path.exists(time_trace_report_path))
1908 container.execute(
"apt-get install -y g++")
1909 container.execute(
"apt-get remove -y clang-18")
1913 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1916 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1918 except DockerException
as e:
1919 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1923 Check if NS3_NINJA_TRACE feature is working
1924 Ninja's .ninja_log conversion to about://tracing
1925 json format conversion with Ninjatracing
1931 container.execute(
"apt-get update")
1932 container.execute(
"apt-get remove -y g++")
1933 container.execute(
"apt-get install -y python3 cmake g++-11 clang-18")
1938 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1940 except DockerException
as e:
1941 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1946 container.execute(
"apt-get install -y ninja-build")
1950 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1952 except DockerException
as e:
1953 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1955 container.execute(
"apt-get install -y git")
1959 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1961 except DockerException
as e:
1962 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1965 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1966 if os.path.exists(ninja_trace_path):
1967 os.remove(ninja_trace_path)
1970 container.execute(
"./ns3 build core")
1974 container.execute(
"./ns3 build ninjaTrace")
1975 except DockerException
as e:
1976 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1979 self.assertTrue(os.path.exists(ninja_trace_path))
1980 trace_size = os.stat(ninja_trace_path).st_size
1981 os.remove(ninja_trace_path)
1988 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1990 except DockerException
as e:
1991 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
1994 container.execute(
"./ns3 build core")
1998 container.execute(
"./ns3 build ninjaTrace")
1999 except DockerException
as e:
2000 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
2002 self.assertTrue(os.path.exists(ninja_trace_path))
2003 timetrace_size = os.stat(ninja_trace_path).st_size
2004 os.remove(ninja_trace_path)
2007 self.assertGreater(timetrace_size, trace_size)
2011 Check if precompiled headers are being enabled correctly.
2021 container.execute(
"apt-get update")
2022 container.execute(
"apt-get install -y python3 cmake ccache g++")
2024 container.execute(
"./ns3 configure")
2025 except DockerException
as e:
2026 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2030 Check for regressions in test object build.
2033 return_code, stdout, stderr =
run_ns3(
"configure")
2034 self.assertEqual(return_code, 0)
2036 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2037 self.assertFalse(os.path.exists(test_module_cache))
2039 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2040 self.assertEqual(return_code, 0)
2041 self.assertTrue(os.path.exists(test_module_cache))
2045 Check for regressions in a bare ns-3 configuration.
2052 container.execute(
"apt-get update")
2053 container.execute(
"apt-get install -y python3 cmake g++")
2057 stdout = container.execute(
"./ns3 configure -d release")
2058 except DockerException
as e:
2060 self.
config_ok(return_code, stdout, stdout)
2067 Tests ns3 regarding building the project
2072 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2081 Try building the core library
2084 return_code, stdout, stderr =
run_ns3(
"build core")
2085 self.assertEqual(return_code, 0)
2086 self.assertIn(
"Built target core", stdout)
2090 Try building core-test library without tests enabled
2094 return_code, stdout, stderr =
run_ns3(
"build core-test")
2095 self.assertEqual(return_code, 1)
2096 self.assertIn(
"Target to build does not exist: core-test", stdout)
2100 Try building the project:
2103 return_code, stdout, stderr =
run_ns3(
"build")
2104 self.assertEqual(return_code, 0)
2105 self.assertIn(
"Built target", stdout)
2107 self.assertTrue(os.path.exists(program), program)
2108 self.assertIn(cmake_build_project_command, stdout)
2112 Try hiding task lines
2115 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2116 self.assertEqual(return_code, 0)
2117 self.assertIn(cmake_build_project_command, stdout)
2121 Try removing an essential file to break the build
2125 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2126 attribute_cc_bak_path = attribute_cc_path +
".bak"
2127 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2130 return_code, stdout, stderr =
run_ns3(
"build")
2131 self.assertNotEqual(return_code, 0)
2134 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2137 return_code, stdout, stderr =
run_ns3(
"build")
2138 self.assertEqual(return_code, 0)
2142 Test if changing the version file affects the library names
2148 version_file = os.sep.join([ns3_path,
"VERSION"])
2149 with open(version_file,
"w", encoding=
"utf-8")
as f:
2153 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2154 self.
config_ok(return_code, stdout, stderr)
2157 return_code, stdout, stderr =
run_ns3(
"build")
2158 self.assertEqual(return_code, 0)
2159 self.assertIn(
"Built target", stdout)
2165 for program
in new_programs:
2166 self.assertTrue(os.path.exists(program))
2173 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2174 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2175 for library
in new_libraries:
2176 self.assertNotIn(
"libns3-dev", library)
2177 self.assertIn(
"libns3-00", library)
2178 self.assertTrue(os.path.exists(library))
2181 with open(version_file,
"w", encoding=
"utf-8")
as f:
2186 Try setting a different output directory and if everything is
2187 in the right place and still working correctly
2192 return_code, stdout, stderr =
run_ns3(
"build")
2193 self.assertEqual(return_code, 0)
2208 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2209 relative_path = os.sep.join([
"build",
"release"])
2210 for different_out_dir
in [absolute_path, relative_path]:
2211 return_code, stdout, stderr =
run_ns3(
2212 'configure -G "{generator}" --out="%s"' % different_out_dir
2214 self.
config_ok(return_code, stdout, stderr)
2216 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2225 for program
in new_programs:
2226 self.assertTrue(os.path.exists(program))
2230 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2231 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2232 for library
in new_libraries:
2233 self.assertTrue(os.path.exists(library))
2236 shutil.rmtree(absolute_path)
2239 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2240 self.
config_ok(return_code, stdout, stderr)
2242 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2251 for program
in new_programs:
2252 self.assertTrue(os.path.exists(program))
2257 for library
in libraries:
2258 self.assertTrue(os.path.exists(library))
2262 Tries setting a ns3 version, then installing it.
2263 After that, tries searching for ns-3 with CMake's find_package(ns3).
2264 Finally, tries using core library in a 3rd-party project
2269 for library
in libraries:
2273 version_file = os.sep.join([ns3_path,
"VERSION"])
2274 with open(version_file,
"w", encoding=
"utf-8")
as f:
2278 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2279 return_code, stdout, stderr =
run_ns3(
2280 'configure -G "{generator}" --prefix="%s"' % install_prefix
2282 self.
config_ok(return_code, stdout, stderr)
2293 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2294 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2298 installed_libraries_list =
";".join(installed_libraries)
2299 for library
in libraries:
2300 library_name = os.path.basename(library)
2301 self.assertIn(library_name, installed_libraries_list)
2305 missing_headers = list(
2306 set([os.path.basename(x)
for x
in headers])
2307 - (set([os.path.basename(x)
for x
in installed_headers]))
2309 self.assertEqual(len(missing_headers), 0)
2312 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2313 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2315 #include <ns3/core-module.h>
2316 using namespace ns3;
2319 Simulator::Stop (Seconds (1.0));
2321 Simulator::Destroy ();
2329 for version
in [
"",
"3.01",
"3.00"]:
2330 ns3_import_methods = []
2333 cmake_find_package_import =
"""
2334 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2335 find_package(ns3 {version} COMPONENTS core)
2336 target_link_libraries(test PRIVATE ns3::core)
2337 """.format(lib=(
"lib64" if lib64
else "lib"), version=version)
2338 ns3_import_methods.append(cmake_find_package_import)
2341 pkgconfig_import =
"""
2342 list(APPEND CMAKE_PREFIX_PATH ./)
2343 include(FindPkgConfig)
2344 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2345 target_link_libraries(test PUBLIC PkgConfig::ns3)
2347 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2349 if shutil.which(
"pkg-config"):
2350 ns3_import_methods.append(pkgconfig_import)
2353 for import_method
in ns3_import_methods:
2354 test_cmake_project =
"""
2355 cmake_minimum_required(VERSION 3.20..3.20)
2356 project(ns3_consumer CXX)
2357 set(CMAKE_CXX_STANDARD 23)
2358 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2359 add_executable(test main.cpp)
2362 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2363 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2364 f.write(test_cmake_project)
2367 cmake = shutil.which(
"cmake")
2370 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2371 generator=platform_makefiles
2376 if version ==
"3.00":
2377 self.assertEqual(return_code, 1)
2378 if import_method == cmake_find_package_import:
2380 'Could not find a configuration file for package "ns3" that is compatible',
2381 stderr.replace(
"\n",
""),
2383 elif import_method == pkgconfig_import:
2384 self.assertIn(
"not found", stderr.replace(
"\n",
""))
2386 raise Exception(
"Unknown import type")
2388 self.assertEqual(return_code, 0)
2389 self.assertIn(
"Build files", stdout)
2392 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2394 if version ==
"3.00":
2395 self.assertEqual(return_code, 2, msg=stdout + stderr)
2396 self.assertGreater(len(stderr), 0)
2398 self.assertEqual(return_code, 0)
2399 self.assertIn(
"Built target", stdout)
2403 test_program = os.path.join(install_prefix,
"test.exe")
2404 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2406 "PATH": env_sep.join(
2407 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2411 test_program =
"./test"
2414 test_program,
"", cwd=install_prefix, env=env
2416 self.assertEqual(return_code, 0)
2419 return_code, stdout, stderr =
run_ns3(
"uninstall")
2420 self.assertIn(
"Built target uninstall", stdout)
2423 os.remove(version_file)
2424 with open(version_file,
"w", encoding=
"utf-8")
as f:
2429 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2434 "scratch/scratch-simulator":
"scratch-simulator",
2435 "scratch/scratch-simulator.cc":
"scratch-simulator",
2436 "scratch-simulator":
"scratch-simulator",
2437 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2438 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2439 "scratch-subdir":
"subdir_scratch-subdir",
2441 for target_to_run, target_cmake
in targets.items():
2443 build_line =
"target scratch_%s" % target_cmake
2444 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2445 self.assertEqual(return_code, 0)
2446 self.assertIn(build_line, stdout)
2449 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2450 self.assertEqual(return_code, 0)
2451 self.assertIn(build_line, stdout)
2452 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2453 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2457 Test if ns3 can alert correctly in case a shortcut collision happens
2462 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2463 self.assertEqual(return_code, 0)
2466 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2469 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2470 self.assertEqual(return_code, 0)
2473 return_code, stdout, stderr =
run_ns3(
"build second")
2474 self.assertEqual(return_code, 1)
2476 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2477 stdout.replace(os.sep,
"/"),
2481 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2482 self.assertEqual(return_code, 0)
2486 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2487 self.assertEqual(return_code, 0)
2491 return_code, stdout, stderr =
run_ns3(
"run second")
2492 self.assertEqual(return_code, 1)
2494 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2495 stdout.replace(os.sep,
"/"),
2499 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2500 self.assertEqual(return_code, 0)
2503 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2504 self.assertEqual(return_code, 0)
2507 os.remove(
"./scratch/second.cc")
2511 Test if we can build a static ns-3 library and link it to static programs
2514 if (
not win32)
and (arch ==
"aarch64"):
2515 if platform.libc_ver()[0] ==
"glibc":
2516 from packaging.version
import Version
2518 if Version(platform.libc_ver()[1]) < Version(
"2.37"):
2520 "Static linking on ARM64 requires glibc 2.37 where fPIC was enabled (fpic is limited in number of GOT entries)"
2524 return_code, stdout, stderr =
run_ns3(
2525 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2531 self.assertEqual(return_code, 1)
2532 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2535 self.assertEqual(return_code, 0)
2538 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2539 self.assertEqual(return_code, 0)
2540 self.assertIn(
"Built target", stdout)
2546 Test if we can use python bindings
2551 except ModuleNotFoundError:
2552 self.skipTest(
"Cppyy was not found")
2555 return_code, stdout, stderr =
run_ns3(
2556 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2560 self.assertEqual(return_code, 0)
2563 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2564 self.assertEqual(return_code, 0)
2567 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2568 self.assertEqual(return_code, 0)
2572 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2574 self.assertEqual(return_code, 0)
2578 Test if we had regressions with brite, click and openflow modules
2579 that depend on homonymous libraries
2582 if shutil.which(
"git")
is None:
2583 self.skipTest(
"Missing git")
2586 self.skipTest(
"Optional components are not supported on Windows")
2589 return_code, stdout, stderr =
run_ns3(
2590 "configure --disable-werror -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON"
2592 self.assertEqual(return_code, 0)
2596 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2597 self.assertEqual(return_code, 0)
2601 Test if we can link contrib modules to src modules
2604 if shutil.which(
"git")
is None:
2605 self.skipTest(
"Missing git")
2607 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2608 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2610 if os.path.exists(destination_contrib):
2611 shutil.rmtree(destination_contrib)
2612 if os.path.exists(destination_src):
2613 shutil.rmtree(destination_src)
2617 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2618 destination_contrib,
2621 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2626 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2627 self.assertEqual(return_code, 0)
2630 return_code, stdout, stderr =
run_ns3(
"run source-example")
2631 self.assertEqual(return_code, 0)
2634 shutil.rmtree(destination_contrib)
2635 shutil.rmtree(destination_src)
2640 Tests ns3 usage in more realistic scenarios
2645 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2646 Here examples, tests and documentation are also enabled.
2653 return_code, stdout, stderr =
run_ns3(
2654 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2656 self.
config_ok(return_code, stdout, stderr)
2659 self.assertTrue(os.path.exists(ns3_lock_filename))
2665 self.assertTrue(os.path.exists(ns3_lock_filename))
2672 Try to build the project
2675 return_code, stdout, stderr =
run_ns3(
"build")
2676 self.assertEqual(return_code, 0)
2677 self.assertIn(
"Built target", stdout)
2679 self.assertTrue(os.path.exists(program))
2682 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2683 self.assertIn(cmake_build_project_command, stdout)
2687 Try to build and run test-runner
2690 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2691 self.assertEqual(return_code, 0)
2692 self.assertIn(
"Built target test-runner", stdout)
2697 Try to build and run a library
2700 return_code, stdout, stderr =
run_ns3(
"run core")
2701 self.assertEqual(return_code, 1)
2702 self.assertIn(
"Couldn't find the specified program: core", stderr)
2706 Try to build and run an unknown target
2709 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2710 self.assertEqual(return_code, 1)
2711 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2715 Try to run test-runner without building
2718 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2719 self.assertEqual(return_code, 0)
2721 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2722 self.assertEqual(return_code, 0)
2723 self.assertNotIn(
"Built target test-runner", stdout)
2728 Test ns3 fails to run a library
2731 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2732 self.assertEqual(return_code, 1)
2733 self.assertIn(
"Couldn't find the specified program: core", stderr)
2737 Test ns3 fails to run an unknown program
2740 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2741 self.assertEqual(return_code, 1)
2742 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2746 Test if scratch simulator is executed through gdb and lldb
2749 if shutil.which(
"gdb")
is None:
2750 self.skipTest(
"Missing gdb")
2752 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2753 self.assertEqual(return_code, 0)
2755 return_code, stdout, stderr =
run_ns3(
2756 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2758 self.assertEqual(return_code, 0)
2759 self.assertIn(
"scratch-simulator", stdout)
2761 self.assertIn(
"GNU gdb", stdout)
2763 self.assertIn(
"No debugging symbols found", stdout)
2767 Test if scratch simulator is executed through valgrind
2770 if shutil.which(
"valgrind")
is None:
2771 self.skipTest(
"Missing valgrind")
2773 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2774 self.assertEqual(return_code, 0)
2776 return_code, stdout, stderr =
run_ns3(
2777 "run scratch-simulator --valgrind --verbose --no-build"
2779 self.assertEqual(return_code, 0)
2780 self.assertIn(
"scratch-simulator", stderr)
2781 self.assertIn(
"Memcheck", stderr)
2785 Test the doxygen target that does trigger a full build
2788 if shutil.which(
"doxygen")
is None:
2789 self.skipTest(
"Missing doxygen")
2791 if shutil.which(
"bash")
is None:
2792 self.skipTest(
"Missing bash")
2794 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2796 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2797 for filename
in doxygen_files:
2798 file_path = os.sep.join([doc_folder, filename])
2799 if os.path.exists(file_path):
2800 os.remove(file_path)
2807 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2808 self.assertEqual(return_code, 0)
2810 self.assertIn(
"Built target doxygen", stdout)
2814 Test the doxygen target that doesn't trigger a full build
2817 if shutil.which(
"doxygen")
is None:
2818 self.skipTest(
"Missing doxygen")
2826 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2827 self.assertEqual(return_code, 0)
2829 self.assertIn(
"Built target doxygen-no-build", stdout)
2833 Test every individual target for Sphinx-based documentation
2836 if shutil.which(
"sphinx-build")
is None:
2837 self.skipTest(
"Missing sphinx")
2839 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2842 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2844 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2845 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2846 if os.path.exists(doc_build_folder):
2847 shutil.rmtree(doc_build_folder)
2848 if os.path.exists(doc_temp_folder):
2849 shutil.rmtree(doc_temp_folder)
2852 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2853 self.assertEqual(return_code, 0, target)
2855 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2858 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2859 self.assertTrue(os.path.exists(doc_build_folder))
2862 for build_type
in [
"latex",
"html",
"singlehtml"]:
2863 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2867 Test the documentation target that builds
2868 both doxygen and sphinx based documentation
2871 if shutil.which(
"doxygen")
is None:
2872 self.skipTest(
"Missing doxygen")
2873 if shutil.which(
"sphinx-build")
is None:
2874 self.skipTest(
"Missing sphinx")
2876 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2885 for target
in [
"manual",
"models",
"tutorial"]:
2886 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2887 if os.path.exists(doc_build_folder):
2888 shutil.rmtree(doc_build_folder)
2890 return_code, stdout, stderr =
run_ns3(
"docs all")
2891 self.assertEqual(return_code, 0)
2893 self.assertIn(
"Built target sphinx", stdout)
2895 self.assertIn(
"Built target doxygen", stdout)
2899 Try to set ownership of scratch-simulator from current user to root,
2900 and change execution permissions
2905 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2908 if sudo_password
is None:
2909 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2912 self.assertFalse(enable_sudo
is True)
2915 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2916 self.assertEqual(return_code, 0)
2917 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2919 scratch_simulator_path = list(
2920 filter(
lambda x: x
if "scratch-simulator" in x
else None, self.
ns3_executables)
2922 prev_fstat = os.stat(scratch_simulator_path)
2925 return_code, stdout, stderr =
run_ns3(
2926 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2928 self.assertEqual(return_code, 0)
2929 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2931 fstat = os.stat(scratch_simulator_path)
2937 likely_fuse_mount = (
2938 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2939 )
and prev_fstat.st_uid == 0
2941 if win32
or likely_fuse_mount:
2942 self.skipTest(
"Windows or likely a FUSE mount")
2945 self.assertEqual(fstat.st_uid, 0)
2947 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2951 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2952 self.assertEqual(return_code, 0)
2956 self.assertTrue(enable_sudo)
2960 if os.path.exists(executable):
2961 os.remove(executable)
2964 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2965 self.assertEqual(return_code, 0)
2968 self.assertIn(
"chown root", stdout)
2969 self.assertIn(
"chmod u+s", stdout)
2971 self.assertIn(os.path.basename(executable), stdout)
2974 fstat = os.stat(scratch_simulator_path)
2975 self.assertEqual(fstat.st_uid, 0)
2977 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2982 Check if command template is working
2987 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
2988 self.assertEqual(return_code0, 2)
2989 self.assertIn(
"argument --command-template: expected one argument", stderr0)
2991 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
2992 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
2993 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
2994 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
2995 for stderr
in [stderr1, stderr2, stderr3]:
2996 self.assertIn(
"not all arguments converted during string formatting", stderr)
2999 return_code4, stdout4, _ =
run_ns3(
3000 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
3002 return_code5, stdout5, _ =
run_ns3(
3003 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
3005 self.assertEqual((return_code4, return_code5), (0, 0))
3007 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3008 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3012 Check if all flavors of different argument passing to
3013 executable targets are working
3018 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3019 return_code1, stdout1, stderr1 =
run_ns3(
3020 'run sample-simulator --command-template="%s --help" --verbose'
3022 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3024 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3025 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3026 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3027 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3030 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3031 return_code1, stdout1, stderr1 =
run_ns3(
3032 'run sample-simulator --command-template="%s --help" --no-build'
3034 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3035 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3036 self.assertEqual(stdout0, stdout1)
3037 self.assertEqual(stdout1, stdout2)
3038 self.assertEqual(stderr0, stderr1)
3039 self.assertEqual(stderr1, stderr2)
3042 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3043 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3044 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3046 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3047 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3048 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3049 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3052 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3053 return_code, stdout, stderr =
run_ns3(cmd)
3054 self.assertEqual(return_code, 0)
3060 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3065 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3066 cmd1 =
"run sample-simulator --PrintTypeIds"
3068 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3069 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3070 self.assertEqual((return_code0, return_code1), (1, 1))
3071 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3072 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3076 Test if scratch simulator is executed through lldb
3079 if shutil.which(
"lldb")
is None:
3080 self.skipTest(
"Missing lldb")
3082 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3083 self.assertEqual(return_code, 0)
3085 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3086 self.assertEqual(return_code, 0)
3087 self.assertIn(
"scratch-simulator", stdout)
3088 self.assertIn(
"(lldb) target create", stdout)
3092 Test if CPM and Vcpkg package managers are working properly
3096 return_code, stdout, stderr =
run_ns3(
"clean")
3097 self.assertEqual(return_code, 0)
3100 if os.path.exists(
"vcpkg"):
3101 shutil.rmtree(
"vcpkg")
3104 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3106 if os.path.exists(destination_src):
3107 shutil.rmtree(destination_src)
3111 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3117 container.execute(
"apt-get update")
3118 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3123 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3124 self.skipTest(
"Armadillo is already installed")
3125 except DockerException
as e:
3129 return_code, stdout, stderr =
run_ns3(
"clean")
3130 self.assertEqual(return_code, 0)
3133 container.execute(
"apt-get install -y git")
3138 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3140 except DockerException
as e:
3145 container.execute(
"./ns3 build test-package-managers")
3146 except DockerException
as e:
3150 return_code, stdout, stderr =
run_ns3(
"clean")
3151 self.assertEqual(return_code, 0)
3153 if arch !=
"aarch64":
3155 container.execute(
"apt-get install -y zip unzip tar curl")
3158 container.execute(
"apt-get install -y pkg-config gfortran")
3162 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3163 except DockerException
as e:
3168 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3169 except DockerException
as e:
3174 container.execute(
"./ns3 build test-package-managers")
3175 except DockerException
as e:
3179 if os.path.exists(destination_src):
3180 shutil.rmtree(destination_src)
3184 Test if test.py and command-template handles empty spaces in executable paths correctly
3188 return_code, stdout, stderr =
run_ns3(
"clean")
3189 self.assertEqual(return_code, 0)
3193 container.execute(
"apt-get update")
3194 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3197 test_path =
"/path with empty spaces/ns-3-dev"
3199 container.execute(f
'mkdir -p "{test_path}"')
3200 container.execute(f
'cp -R ./ "{test_path}"')
3201 except DockerException
as e:
3207 './ns3 configure --enable-examples --enable-tests --filter-module-examples-and-tests="core;sixlowpan"',
3210 except DockerException
as e:
3215 container.execute(
"./test.py", workdir=test_path)
3216 except DockerException
as e:
3220 return_code, stdout, stderr =
run_ns3(
"clean")
3221 self.assertEqual(return_code, 0)
3226 ns-3 tests to control the quality of the repository over time
3231 Check if images in the docs are above a brightness threshold.
3232 This should prevent screenshots with dark UI themes.
3235 if shutil.which(
"convert")
is None:
3236 self.skipTest(
"Imagemagick was not found")
3238 from pathlib
import Path
3241 image_extensions = [
"png",
"jpg"]
3243 for extension
in image_extensions:
3244 images += list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3245 images += list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3248 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3252 brightness_threshold = 50
3253 for image
in images:
3254 brightness = subprocess.check_output(
3255 imagemagick_get_image_brightness.format(image=image).split()
3257 brightness = float(brightness.decode().strip(
"'\""))
3260 brightness_threshold,
3261 "Image darker than threshold (%d < %d): %s"
3262 % (brightness, brightness_threshold, image),
3267 Check if one of the log statements of examples/tests contains/exposes a bug.
3271 return_code, stdout, stderr =
run_ns3(
3272 'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
3274 self.assertEqual(return_code, 0)
3278 "test.py",
"", python=
True, env={
"TEST_LOGS":
"1"}
3280 self.assertEqual(return_code, 0)
3285 ns-3 complementary tests, allowed to fail, to help control
3286 the quality of the repository over time, by checking the
3287 state of URLs listed and more
3292 Test if all urls in source files are alive
3301 self.skipTest(
"Django URL validators are not available")
3308 urllib3.disable_warnings()
3311 self.skipTest(
"Requests library is not available")
3313 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3316 whitelisted_urls = {
3317 "https://gitlab.com/your-user-name/ns-3-dev",
3318 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3319 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3320 "https://www.nsnam.org/releases/ns-3-x",
3321 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3322 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3323 "https://ns-buildmaster.ee.washington.edu:8010/",
3325 "https://cmake.org/cmake/help/latest/manual/cmake-",
3326 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3328 "http://www.lysator.liu.se/~alla/dia/",
3330 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3331 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3332 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3333 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3334 "https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch",
3335 "http://www.nsnam.org/bugzilla/show_bug.cgi?id=",
3337 "http://www.research.att.com/info/kpv/",
3338 "http://www.research.att.com/~gsf/",
3339 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3340 "http://scan5.coverity.com/cgi-bin/upload.py",
3342 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3343 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3347 files_and_urls = set()
3349 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3350 for root, dirs, files
in os.walk(topdir):
3352 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3355 filepath = os.path.join(root, file)
3358 if not os.path.isfile(filepath):
3362 if file.endswith(
".svg"):
3366 with open(filepath,
"r", encoding=
"utf-8")
as f:
3367 matches = regex.findall(f.read())
3373 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3375 except UnicodeDecodeError:
3376 skipped_files.append(filepath)
3380 for url
in set(urls) - unique_urls - whitelisted_urls:
3381 unique_urls.add(url)
3382 files_and_urls.add((filepath, url))
3385 from django.core.exceptions
import ValidationError
3386 from django.core.validators
import URLValidator
3388 validate_url = URLValidator()
3392 "User-Agent":
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
3396 def test_file_url(args):
3397 test_filepath, test_url = args
3398 dead_link_msg =
None
3402 validate_url(test_url)
3403 except ValidationError:
3404 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3405 except Exception
as e:
3406 self.assertEqual(
False,
True, msg=e.__str__())
3408 if dead_link_msg
is not None:
3409 return dead_link_msg
3417 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3420 if response.status_code
in [200, 301]:
3421 dead_link_msg =
None
3426 if response.status_code
in [302, 308, 500, 503]:
3427 if response.reason.lower()
in [
3429 "moved temporarily",
3430 "permanent redirect",
3432 "service temporarily unavailable",
3434 dead_link_msg =
None
3438 dead_link_msg =
"%s: URL %s: returned code %d" % (
3441 response.status_code,
3443 except requests.exceptions.InvalidURL:
3444 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3445 except requests.exceptions.SSLError:
3446 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3447 except requests.exceptions.TooManyRedirects:
3448 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3449 except Exception
as e:
3451 error_msg = e.args[0].reason.__str__()
3452 except AttributeError:
3453 error_msg = e.args[0]
3454 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3460 return dead_link_msg
3463 from concurrent.futures
import ThreadPoolExecutor
3465 with ThreadPoolExecutor(max_workers=100)
as executor:
3466 dead_links = list(executor.map(test_file_url, list(files_and_urls)))
3469 dead_links = list(sorted(filter(
lambda x: x
is not None, dead_links)))
3470 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3474 Test if all tests can be executed without hitting major memory bugs
3477 return_code, stdout, stderr =
run_ns3(
3478 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3480 self.assertEqual(return_code, 0)
3482 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3483 self.assertEqual(test_return_code, 0)
3492 test_completeness = {
3494 NS3UnusedSourcesTestCase,
3498 NS3CommonSettingsTestCase,
3499 NS3ConfigureBuildProfileTestCase,
3500 NS3ConfigureTestCase,
3501 NS3BuildBaseTestCase,
3502 NS3ExpectedUseTestCase,
3505 NS3UnusedSourcesTestCase,
3507 NS3CommonSettingsTestCase,
3508 NS3ConfigureBuildProfileTestCase,
3509 NS3ConfigureTestCase,
3510 NS3BuildBaseTestCase,
3511 NS3ExpectedUseTestCase,
3512 NS3QualityControlTestCase,
3515 NS3DependenciesTestCase,
3516 NS3QualityControlThatCanFailTestCase,
3522 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3523 parser.add_argument(
3524 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3526 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3527 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3528 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3529 parser.add_argument(
"-f",
"--failfast", action=
"store_true", default=
False)
3530 args = parser.parse_args(sys.argv[1:])
3532 loader = unittest.TestLoader()
3533 suite = unittest.TestSuite()
3536 for testCase
in test_completeness[args.completeness]:
3537 suite.addTests(loader.loadTestsFromTestCase(testCase))
3542 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3544 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3545 tests_to_remove = set(tests) - set(tests_to_run)
3546 for test_to_remove
in tests_to_remove:
3547 suite._tests.remove(tests[test_to_remove])
3550 if args.resume_from_test_name:
3552 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3553 keys = list(tests.keys())
3555 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3556 suite._tests.remove(tests[keys[0]])
3560 ns3rc_script_bak = ns3rc_script +
".bak"
3561 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3562 shutil.move(ns3rc_script, ns3rc_script_bak)
3565 runner = unittest.TextTestRunner(failfast=args.failfast, verbosity=1
if args.quiet
else 2)
3569 if os.path.exists(ns3rc_script_bak):
3570 shutil.move(ns3rc_script_bak, ns3rc_script)
3573if __name__ ==
"__main__":
Python-on-whales wrapper for Docker-based ns-3 tests.
__init__(self, unittest.TestCase currentTestCase, str containerName="ubuntu:latest")
Create and start container with containerName in the current ns-3 directory.
__enter__(self)
Return the managed container when entiring the block "with DockerContainerManager() as container".
__exit__(self, exc_type, exc_val, exc_tb)
Clean up the managed container at the end of the block "with DockerContainerManager() as container".
container
The Python-on-whales container instance.
Generic test case with basic function inherited by more complex tests.
config_ok(self, return_code, stdout, stderr)
Check if configuration for release mode worked normally.
setUp(self)
Clean configuration/build artifacts before testing configuration and build settings After configuring...
ns3_executables
ns3_executables holds a list of executables in .lock-ns3 # noqa
ns3_modules
ns3_modules holds a list to the modules enabled stored in .lock-ns3 # noqa
Tests ns3 regarding building the project.
test_08_InstallationAndUninstallation(self)
Tries setting a ns3 version, then installing it.
test_12_CppyyBindings(self)
Test if we can use python bindings.
test_13_FetchOptionalComponents(self)
Test if we had regressions with brite, click and openflow modules that depend on homonymous libraries...
test_07_OutputDirectory(self)
Try setting a different output directory and if everything is in the right place and still working co...
test_02_BuildNonExistingTargets(self)
Try building core-test library without tests enabled.
test_01_BuildExistingTargets(self)
Try building the core library.
setUp(self)
Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned.
test_04_BuildProjectNoTaskLines(self)
Try hiding task lines.
test_11_StaticBuilds(self)
Test if we can build a static ns-3 library and link it to static programs.
test_06_TestVersionFile(self)
Test if changing the version file affects the library names.
test_14_LinkContribModuleToSrcModule(self)
Test if we can link contrib modules to src modules.
test_03_BuildProject(self)
Try building the project:
test_09_Scratches(self)
Tries to build scratch-simulator and subdir/scratch-simulator-subdir.
test_05_BreakBuild(self)
Try removing an essential file to break the build.
test_10_AmbiguityCheck(self)
Test if ns3 can alert correctly in case a shortcut collision happens.
ns3_libraries
ns3_libraries holds a list of built module libraries # noqa
ns3 tests related to generic options
test_01_NoOption(self)
Test not passing any arguments to.
test_05_CheckVersion(self)
Test only passing 'show version' argument to ns3.
test_04_CheckProfile(self)
Test only passing 'show profile' argument to ns3.
test_03_CheckConfig(self)
Test only passing 'show config' argument to ns3.
setUp(self)
Clean configuration/build artifacts before common commands.
test_02_NoTaskLines(self)
Test only passing –quiet argument to ns3.
ns-3 tests related to dependencies
test_01_CheckIfIncludedHeadersMatchLinkedModules(self)
Checks if headers from different modules (src/A, contrib/B) that are included by the current module (...
Tests ns3 usage in more realistic scenarios.
test_12_SphinxDocumentation(self)
Test every individual target for Sphinx-based documentation.
test_03_BuildAndRunExistingLibraryTarget(self)
Try to build and run a library.
test_01_BuildProject(self)
Try to build the project.
test_08_RunNoBuildGdb(self)
Test if scratch simulator is executed through gdb and lldb.
test_11_DoxygenWithoutBuild(self)
Test the doxygen target that doesn't trigger a full build.
test_06_RunNoBuildExistingLibraryTarget(self)
Test ns3 fails to run a library.
test_14_EnableSudo(self)
Try to set ownership of scratch-simulator from current user to root, and change execution permissions...
setUp(self)
Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned Here examples,...
test_02_BuildAndRunExistingExecutableTarget(self)
Try to build and run test-runner.
test_18_CpmAndVcpkgManagers(self)
Test if CPM and Vcpkg package managers are working properly.
test_15_CommandTemplate(self)
Check if command template is working.
test_07_RunNoBuildNonExistingExecutableTarget(self)
Test ns3 fails to run an unknown program.
test_05_RunNoBuildExistingExecutableTarget(self)
Try to run test-runner without building.
test_16_ForwardArgumentsToRunTargets(self)
Check if all flavors of different argument passing to executable targets are working.
test_17_RunNoBuildLldb(self)
Test if scratch simulator is executed through lldb.
test_19_EmptySpaceHandlingOnTestAndCommandTemplate(self)
Test if test.py and command-template handles empty spaces in executable paths correctly.
test_09_RunNoBuildValgrind(self)
Test if scratch simulator is executed through valgrind.
test_04_BuildAndRunNonExistingTarget(self)
Try to build and run an unknown target.
test_13_Documentation(self)
Test the documentation target that builds both doxygen and sphinx based documentation.
test_10_DoxygenWithBuild(self)
Test the doxygen target that does trigger a full build.
ns-3 tests to control the quality of the repository over time
test_02_CheckForBrokenLogs(self)
Check if one of the log statements of examples/tests contains/exposes a bug.
test_01_CheckImageBrightness(self)
Check if images in the docs are above a brightness threshold.
ns-3 complementary tests, allowed to fail, to help control the quality of the repository over time,...
test_01_CheckForDeadLinksInSources(self)
Test if all urls in source files are alive.
test_02_MemoryCheckWithSanitizers(self)
Test if all tests can be executed without hitting major memory bugs.
ns-3 tests to check if the source code, whitespaces and CMake formatting are according to the coding ...
test_01_CheckCMakeFormat(self)
Check if there is any difference between tracked file after applying cmake-format.
None setUp(self)
Import GitRepo and load the original diff state of the repository before the tests.
ns-3 tests related to checking if source files were left behind, not being used by CMake
dict directory_and_files
dictionary containing directories with .cc source files # noqa
test_01_UnusedExampleSources(self)
Test if all example source files are being used in their respective CMakeLists.txt.
test_03_UnusedUtilsSources(self)
Test if all utils source files are being used in their respective CMakeLists.txt.
setUp(self)
Scan all C++ source files and add them to a list based on their path.
test_02_UnusedModuleSources(self)
Test if all module source files are being used in their respective CMakeLists.txt.
read_lock_entry(entry)
Read interesting entries from the .lock-ns3 file.
get_libraries_list(lib_outdir=usual_lib_outdir)
Gets a list of built libraries.
get_headers_list(outdir=usual_outdir)
Gets a list of header files.
cmake_build_target_command
run_ns3(args, env=None, generator=platform_makefiles)
Runs the ns3 wrapper script with arguments.
run_program(program, args, python=False, cwd=ns3_path, env=None)
Runs a program with the given arguments and returns a tuple containing (error code,...
get_programs_list()
Extracts the programs list from .lock-ns3.
get_test_enabled()
Check if tests are enabled in the .lock-ns3.