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" % sample_simulator_path,
1478 "mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout
1481 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1484 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1485 self.assertEqual(return_code, 0)
1486 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1489 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1490 self.assertEqual(return_code, 0)
1491 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1493 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1494 self.assertEqual(return_code, 0)
1498 Test if CMake and ns3 fail in the expected ways when:
1499 - examples from modules or general examples fail if they depend on a
1500 library with a name shorter than 4 characters or are disabled when
1501 a library is nonexistent
1502 - a module library passes the configuration but fails to build due to
1506 os.makedirs(
"contrib/borked", exist_ok=
True)
1507 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1510 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1512 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1513 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1517 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1518 LIBRARIES_TO_LINK ${libcore} %s
1520 """ % invalid_or_nonexistent_library)
1522 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1523 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1524 self.assertEqual(return_code, 0)
1525 elif invalid_or_nonexistent_library
in [
"lib"]:
1526 self.assertEqual(return_code, 1)
1527 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1531 return_code, stdout, stderr =
run_ns3(
"build borked")
1532 if invalid_or_nonexistent_library
in [
""]:
1533 self.assertEqual(return_code, 0)
1534 elif invalid_or_nonexistent_library
in [
"lib"]:
1535 self.assertEqual(return_code, 2)
1536 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1537 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1538 self.assertEqual(return_code, 2)
1539 if "lld" in stdout + stderr:
1541 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1543 elif "mold" in stdout + stderr:
1544 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1547 "library not found for -l%s" % invalid_or_nonexistent_library, stderr
1550 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1558 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1562 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1563 LIBRARIES_TO_LINK ${libcore}
1566 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1567 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1571 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1572 LIBRARIES_TO_LINK ${libborked} %s
1574 """ % invalid_or_nonexistent_library)
1576 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1577 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1578 self.assertEqual(return_code, 0)
1579 elif invalid_or_nonexistent_library
in [
"lib"]:
1580 self.assertEqual(return_code, 1)
1581 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1585 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1586 if invalid_or_nonexistent_library
in [
""]:
1587 self.assertEqual(return_code, 0)
1588 elif invalid_or_nonexistent_library
in [
"libf"]:
1589 self.assertEqual(return_code, 2)
1590 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1591 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1592 self.assertEqual(return_code, 1)
1593 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1597 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1601 Test if CMake can properly handle modules containing "lib",
1602 which is used internally as a prefix for module libraries
1606 os.makedirs(
"contrib/calibre", exist_ok=
True)
1607 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1610 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1612 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1616 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1617 LIBRARIES_TO_LINK ${libcore}
1621 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1624 self.assertEqual(return_code, 0)
1627 self.assertIn(
"calibre", stdout)
1631 self.assertNotIn(
"care", stdout)
1633 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1637 return_code, stdout, stderr =
run_ns3(
"build calibre")
1638 self.assertEqual(return_code, 0)
1641 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1645 Test if CMake performance tracing works and produces the
1646 cmake_performance_trace.log file
1649 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1650 if os.path.exists(cmake_performance_trace_log):
1651 os.remove(cmake_performance_trace_log)
1653 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1654 self.assertEqual(return_code, 0)
1656 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1659 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1662 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1666 Check if ENABLE_BUILD_VERSION and version.cache are working
1674 container.execute(
"apt-get update")
1675 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1678 container.execute(
"./ns3 clean")
1681 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1684 if os.path.exists(version_cache_file):
1685 os.remove(version_cache_file)
1689 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1690 except DockerException:
1692 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1695 version_cache_contents = (
1696 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1697 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1698 "VERSION_DIRTY_FLAG = '0'\n"
1699 "VERSION_MAJOR = '3'\n"
1700 "VERSION_MINOR = '0'\n"
1701 "VERSION_PATCH = '0'\n"
1702 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1703 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1704 "VERSION_TAG_DISTANCE = '0'\n"
1705 "VERSION_BUILD_PROFILE = 'debug'\n"
1707 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1708 version.write(version_cache_contents)
1711 container.execute(
"./ns3 clean")
1712 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1713 container.execute(
"./ns3 build core")
1714 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1717 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1718 self.assertEqual(version.read(), version_cache_contents)
1723 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1725 container.execute(
"apt-get install -y git")
1726 container.execute(
"./ns3 clean")
1727 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1728 container.execute(
"./ns3 build core")
1729 except DockerException:
1731 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1732 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1735 container.execute(
"./ns3 clean")
1736 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1737 container.execute(
"./ns3 build core")
1738 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1739 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1740 self.assertNotEqual(version.read(), version_cache_contents)
1743 if os.path.exists(version_cache_file):
1744 os.remove(version_cache_file)
1748 Test filtering in examples and tests from specific modules
1752 return_code, stdout, stderr =
run_ns3(
1753 'configure -G "{generator}" --enable-examples --enable-tests'
1755 self.
config_ok(return_code, stdout, stderr)
1760 return_code, stdout, stderr =
run_ns3(
1761 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1763 self.
config_ok(return_code, stdout, stderr)
1769 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1771 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1774 return_code, stdout, stderr =
run_ns3(
1775 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1777 self.
config_ok(return_code, stdout, stderr)
1785 return_code, stdout, stderr =
run_ns3(
1786 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1788 self.
config_ok(return_code, stdout, stderr)
1796 Check if fast linkers LLD and Mold are correctly found and configured
1803 container.execute(
"apt-get update")
1804 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1807 container.execute(
"./ns3 configure -G Ninja")
1810 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1812 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1814 self.assertIn(
"-fuse-ld=lld", f.read())
1818 container.execute(
"./ns3 build core")
1819 except DockerException:
1820 self.assertTrue(
False,
"Build with lld failed")
1823 if not os.path.exists(f
"./mold-1.4.2-{arch}-linux.tar.gz"):
1825 f
"wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch}-linux.tar.gz"
1828 f
"tar xzfC mold-1.4.2-{arch}-linux.tar.gz /usr/local --strip-components=1"
1833 container.execute(
"./ns3 configure -G Ninja")
1836 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1838 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1840 self.assertIn(
"-fuse-ld=mold", f.read())
1844 container.execute(
"./ns3 build core")
1845 except DockerException:
1846 self.assertTrue(
False,
"Build with mold failed")
1849 os.remove(f
"./mold-1.4.2-{arch}-linux.tar.gz")
1852 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1855 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1857 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1859 self.assertNotIn(
"-fuse-ld=mold", f.read())
1863 Check if NS3_CLANG_TIMETRACE feature is working
1864 Clang's -ftime-trace plus ClangAnalyzer report
1870 container.execute(
"apt-get update")
1871 container.execute(
"apt-get install -y python3 ninja-build cmake clang-18")
1876 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1878 except DockerException
as e:
1879 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1881 container.execute(
"apt-get install -y git")
1886 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1888 except DockerException
as e:
1889 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1892 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1893 if os.path.exists(time_trace_report_path):
1894 os.remove(time_trace_report_path)
1898 container.execute(
"./ns3 build timeTraceReport")
1899 except DockerException
as e:
1900 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1903 self.assertTrue(os.path.exists(time_trace_report_path))
1907 container.execute(
"apt-get install -y g++")
1908 container.execute(
"apt-get remove -y clang-18")
1912 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1915 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1917 except DockerException
as e:
1918 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1922 Check if NS3_NINJA_TRACE feature is working
1923 Ninja's .ninja_log conversion to about://tracing
1924 json format conversion with Ninjatracing
1930 container.execute(
"apt-get update")
1931 container.execute(
"apt-get remove -y g++")
1932 container.execute(
"apt-get install -y python3 cmake g++-11 clang-18")
1937 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1939 except DockerException
as e:
1940 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1945 container.execute(
"apt-get install -y ninja-build")
1949 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1951 except DockerException
as e:
1952 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1954 container.execute(
"apt-get install -y git")
1958 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1960 except DockerException
as e:
1961 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1964 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1965 if os.path.exists(ninja_trace_path):
1966 os.remove(ninja_trace_path)
1969 container.execute(
"./ns3 build core")
1973 container.execute(
"./ns3 build ninjaTrace")
1974 except DockerException
as e:
1975 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1978 self.assertTrue(os.path.exists(ninja_trace_path))
1979 trace_size = os.stat(ninja_trace_path).st_size
1980 os.remove(ninja_trace_path)
1987 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1989 except DockerException
as e:
1990 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
1993 container.execute(
"./ns3 build core")
1997 container.execute(
"./ns3 build ninjaTrace")
1998 except DockerException
as e:
1999 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
2001 self.assertTrue(os.path.exists(ninja_trace_path))
2002 timetrace_size = os.stat(ninja_trace_path).st_size
2003 os.remove(ninja_trace_path)
2006 self.assertGreater(timetrace_size, trace_size)
2010 Check if precompiled headers are being enabled correctly.
2020 container.execute(
"apt-get update")
2021 container.execute(
"apt-get install -y python3 cmake ccache g++")
2023 container.execute(
"./ns3 configure")
2024 except DockerException
as e:
2025 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2029 Check for regressions in test object build.
2032 return_code, stdout, stderr =
run_ns3(
"configure")
2033 self.assertEqual(return_code, 0)
2035 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2036 self.assertFalse(os.path.exists(test_module_cache))
2038 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2039 self.assertEqual(return_code, 0)
2040 self.assertTrue(os.path.exists(test_module_cache))
2044 Check for regressions in a bare ns-3 configuration.
2051 container.execute(
"apt-get update")
2052 container.execute(
"apt-get install -y python3 cmake g++")
2056 stdout = container.execute(
"./ns3 configure -d release")
2057 except DockerException
as e:
2059 self.
config_ok(return_code, stdout, stdout)
2066 Tests ns3 regarding building the project
2071 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2080 Try building the core library
2083 return_code, stdout, stderr =
run_ns3(
"build core")
2084 self.assertEqual(return_code, 0)
2085 self.assertIn(
"Built target core", stdout)
2089 Try building core-test library without tests enabled
2093 return_code, stdout, stderr =
run_ns3(
"build core-test")
2094 self.assertEqual(return_code, 1)
2095 self.assertIn(
"Target to build does not exist: core-test", stdout)
2099 Try building the project:
2102 return_code, stdout, stderr =
run_ns3(
"build")
2103 self.assertEqual(return_code, 0)
2104 self.assertIn(
"Built target", stdout)
2106 self.assertTrue(os.path.exists(program), program)
2107 self.assertIn(cmake_build_project_command, stdout)
2111 Try hiding task lines
2114 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2115 self.assertEqual(return_code, 0)
2116 self.assertIn(cmake_build_project_command, stdout)
2120 Try removing an essential file to break the build
2124 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2125 attribute_cc_bak_path = attribute_cc_path +
".bak"
2126 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2129 return_code, stdout, stderr =
run_ns3(
"build")
2130 self.assertNotEqual(return_code, 0)
2133 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2136 return_code, stdout, stderr =
run_ns3(
"build")
2137 self.assertEqual(return_code, 0)
2141 Test if changing the version file affects the library names
2147 version_file = os.sep.join([ns3_path,
"VERSION"])
2148 with open(version_file,
"w", encoding=
"utf-8")
as f:
2152 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2153 self.
config_ok(return_code, stdout, stderr)
2156 return_code, stdout, stderr =
run_ns3(
"build")
2157 self.assertEqual(return_code, 0)
2158 self.assertIn(
"Built target", stdout)
2164 for program
in new_programs:
2165 self.assertTrue(os.path.exists(program))
2172 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2173 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2174 for library
in new_libraries:
2175 self.assertNotIn(
"libns3-dev", library)
2176 self.assertIn(
"libns3-00", library)
2177 self.assertTrue(os.path.exists(library))
2180 with open(version_file,
"w", encoding=
"utf-8")
as f:
2185 Try setting a different output directory and if everything is
2186 in the right place and still working correctly
2191 return_code, stdout, stderr =
run_ns3(
"build")
2192 self.assertEqual(return_code, 0)
2207 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2208 relative_path = os.sep.join([
"build",
"release"])
2209 for different_out_dir
in [absolute_path, relative_path]:
2210 return_code, stdout, stderr =
run_ns3(
2211 'configure -G "{generator}" --out="%s"' % different_out_dir
2213 self.
config_ok(return_code, stdout, stderr)
2215 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2224 for program
in new_programs:
2225 self.assertTrue(os.path.exists(program))
2229 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2230 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2231 for library
in new_libraries:
2232 self.assertTrue(os.path.exists(library))
2235 shutil.rmtree(absolute_path)
2238 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2239 self.
config_ok(return_code, stdout, stderr)
2241 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2250 for program
in new_programs:
2251 self.assertTrue(os.path.exists(program))
2256 for library
in libraries:
2257 self.assertTrue(os.path.exists(library))
2261 Tries setting a ns3 version, then installing it.
2262 After that, tries searching for ns-3 with CMake's find_package(ns3).
2263 Finally, tries using core library in a 3rd-party project
2268 for library
in libraries:
2272 version_file = os.sep.join([ns3_path,
"VERSION"])
2273 with open(version_file,
"w", encoding=
"utf-8")
as f:
2277 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2278 return_code, stdout, stderr =
run_ns3(
2279 'configure -G "{generator}" --prefix="%s"' % install_prefix
2281 self.
config_ok(return_code, stdout, stderr)
2292 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2293 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2297 installed_libraries_list =
";".join(installed_libraries)
2298 for library
in libraries:
2299 library_name = os.path.basename(library)
2300 self.assertIn(library_name, installed_libraries_list)
2304 missing_headers = list(
2305 set([os.path.basename(x)
for x
in headers])
2306 - (set([os.path.basename(x)
for x
in installed_headers]))
2308 self.assertEqual(len(missing_headers), 0)
2311 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2312 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2314 #include <ns3/core-module.h>
2315 using namespace ns3;
2318 Simulator::Stop (Seconds (1.0));
2320 Simulator::Destroy ();
2328 for version
in [
"",
"3.01",
"3.00"]:
2329 ns3_import_methods = []
2332 cmake_find_package_import =
"""
2333 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2334 find_package(ns3 {version} COMPONENTS core)
2335 target_link_libraries(test PRIVATE ns3::core)
2336 """.format(lib=(
"lib64" if lib64
else "lib"), version=version)
2337 ns3_import_methods.append(cmake_find_package_import)
2340 pkgconfig_import =
"""
2341 list(APPEND CMAKE_PREFIX_PATH ./)
2342 include(FindPkgConfig)
2343 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2344 target_link_libraries(test PUBLIC PkgConfig::ns3)
2346 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2348 if shutil.which(
"pkg-config"):
2349 ns3_import_methods.append(pkgconfig_import)
2352 for import_method
in ns3_import_methods:
2353 test_cmake_project =
"""
2354 cmake_minimum_required(VERSION 3.20..3.20)
2355 project(ns3_consumer CXX)
2356 set(CMAKE_CXX_STANDARD 23)
2357 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2358 add_executable(test main.cpp)
2361 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2362 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2363 f.write(test_cmake_project)
2366 cmake = shutil.which(
"cmake")
2369 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2370 generator=platform_makefiles
2375 if version ==
"3.00":
2376 self.assertEqual(return_code, 1)
2377 if import_method == cmake_find_package_import:
2379 'Could not find a configuration file for package "ns3" that is compatible',
2380 stderr.replace(
"\n",
""),
2382 elif import_method == pkgconfig_import:
2383 self.assertIn(
"not found", stderr.replace(
"\n",
""))
2385 raise Exception(
"Unknown import type")
2387 self.assertEqual(return_code, 0)
2388 self.assertIn(
"Build files", stdout)
2391 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2393 if version ==
"3.00":
2394 self.assertEqual(return_code, 2, msg=stdout + stderr)
2395 self.assertGreater(len(stderr), 0)
2397 self.assertEqual(return_code, 0)
2398 self.assertIn(
"Built target", stdout)
2402 test_program = os.path.join(install_prefix,
"test.exe")
2403 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2405 "PATH": env_sep.join(
2406 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2410 test_program =
"./test"
2413 test_program,
"", cwd=install_prefix, env=env
2415 self.assertEqual(return_code, 0)
2418 return_code, stdout, stderr =
run_ns3(
"uninstall")
2419 self.assertIn(
"Built target uninstall", stdout)
2422 os.remove(version_file)
2423 with open(version_file,
"w", encoding=
"utf-8")
as f:
2428 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2433 "scratch/scratch-simulator":
"scratch-simulator",
2434 "scratch/scratch-simulator.cc":
"scratch-simulator",
2435 "scratch-simulator":
"scratch-simulator",
2436 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2437 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2438 "scratch-subdir":
"subdir_scratch-subdir",
2440 for target_to_run, target_cmake
in targets.items():
2442 build_line =
"target scratch_%s" % target_cmake
2443 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2444 self.assertEqual(return_code, 0)
2445 self.assertIn(build_line, stdout)
2448 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2449 self.assertEqual(return_code, 0)
2450 self.assertIn(build_line, stdout)
2451 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2452 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2456 Test if ns3 can alert correctly in case a shortcut collision happens
2461 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2462 self.assertEqual(return_code, 0)
2465 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2468 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2469 self.assertEqual(return_code, 0)
2472 return_code, stdout, stderr =
run_ns3(
"build second")
2473 self.assertEqual(return_code, 1)
2475 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2476 stdout.replace(os.sep,
"/"),
2480 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2481 self.assertEqual(return_code, 0)
2485 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2486 self.assertEqual(return_code, 0)
2490 return_code, stdout, stderr =
run_ns3(
"run second")
2491 self.assertEqual(return_code, 1)
2493 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2494 stdout.replace(os.sep,
"/"),
2498 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2499 self.assertEqual(return_code, 0)
2502 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2503 self.assertEqual(return_code, 0)
2506 os.remove(
"./scratch/second.cc")
2510 Test if we can build a static ns-3 library and link it to static programs
2513 if (
not win32)
and (arch ==
"aarch64"):
2514 if platform.libc_ver()[0] ==
"glibc":
2515 from packaging.version
import Version
2517 if Version(platform.libc_ver()[1]) < Version(
"2.37"):
2519 "Static linking on ARM64 requires glibc 2.37 where fPIC was enabled (fpic is limited in number of GOT entries)"
2523 return_code, stdout, stderr =
run_ns3(
2524 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2530 self.assertEqual(return_code, 1)
2531 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2534 self.assertEqual(return_code, 0)
2537 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2538 self.assertEqual(return_code, 0)
2539 self.assertIn(
"Built target", stdout)
2545 Test if we can use python bindings
2550 except ModuleNotFoundError:
2551 self.skipTest(
"Cppyy was not found")
2554 return_code, stdout, stderr =
run_ns3(
2555 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2559 self.assertEqual(return_code, 0)
2562 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2563 self.assertEqual(return_code, 0)
2566 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2567 self.assertEqual(return_code, 0)
2571 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2573 self.assertEqual(return_code, 0)
2577 Test if we had regressions with brite, click and openflow modules
2578 that depend on homonymous libraries
2581 if shutil.which(
"git")
is None:
2582 self.skipTest(
"Missing git")
2585 self.skipTest(
"Optional components are not supported on Windows")
2588 return_code, stdout, stderr =
run_ns3(
2589 "configure --disable-werror -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON"
2591 self.assertEqual(return_code, 0)
2595 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2596 self.assertEqual(return_code, 0)
2600 Test if we can link contrib modules to src modules
2603 if shutil.which(
"git")
is None:
2604 self.skipTest(
"Missing git")
2606 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2607 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2609 if os.path.exists(destination_contrib):
2610 shutil.rmtree(destination_contrib)
2611 if os.path.exists(destination_src):
2612 shutil.rmtree(destination_src)
2616 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2617 destination_contrib,
2620 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2625 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2626 self.assertEqual(return_code, 0)
2629 return_code, stdout, stderr =
run_ns3(
"run source-example")
2630 self.assertEqual(return_code, 0)
2633 shutil.rmtree(destination_contrib)
2634 shutil.rmtree(destination_src)
2639 Tests ns3 usage in more realistic scenarios
2644 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2645 Here examples, tests and documentation are also enabled.
2652 return_code, stdout, stderr =
run_ns3(
2653 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2655 self.
config_ok(return_code, stdout, stderr)
2658 self.assertTrue(os.path.exists(ns3_lock_filename))
2664 self.assertTrue(os.path.exists(ns3_lock_filename))
2671 Try to build the project
2674 return_code, stdout, stderr =
run_ns3(
"build")
2675 self.assertEqual(return_code, 0)
2676 self.assertIn(
"Built target", stdout)
2678 self.assertTrue(os.path.exists(program))
2681 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2682 self.assertIn(cmake_build_project_command, stdout)
2686 Try to build and run test-runner
2689 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2690 self.assertEqual(return_code, 0)
2691 self.assertIn(
"Built target test-runner", stdout)
2696 Try to build and run a library
2699 return_code, stdout, stderr =
run_ns3(
"run core")
2700 self.assertEqual(return_code, 1)
2701 self.assertIn(
"Couldn't find the specified program: core", stderr)
2705 Try to build and run an unknown target
2708 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2709 self.assertEqual(return_code, 1)
2710 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2714 Try to run test-runner without building
2717 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2718 self.assertEqual(return_code, 0)
2720 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2721 self.assertEqual(return_code, 0)
2722 self.assertNotIn(
"Built target test-runner", stdout)
2727 Test ns3 fails to run a library
2730 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2731 self.assertEqual(return_code, 1)
2732 self.assertIn(
"Couldn't find the specified program: core", stderr)
2736 Test ns3 fails to run an unknown program
2739 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2740 self.assertEqual(return_code, 1)
2741 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2745 Test if scratch simulator is executed through gdb and lldb
2748 if shutil.which(
"gdb")
is None:
2749 self.skipTest(
"Missing gdb")
2751 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2752 self.assertEqual(return_code, 0)
2754 return_code, stdout, stderr =
run_ns3(
2755 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2757 self.assertEqual(return_code, 0)
2758 self.assertIn(
"scratch-simulator", stdout)
2760 self.assertIn(
"GNU gdb", stdout)
2762 self.assertIn(
"No debugging symbols found", stdout)
2766 Test if scratch simulator is executed through valgrind
2769 if shutil.which(
"valgrind")
is None:
2770 self.skipTest(
"Missing valgrind")
2772 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2773 self.assertEqual(return_code, 0)
2775 return_code, stdout, stderr =
run_ns3(
2776 "run scratch-simulator --valgrind --verbose --no-build"
2778 self.assertEqual(return_code, 0)
2779 self.assertIn(
"scratch-simulator", stderr)
2780 self.assertIn(
"Memcheck", stderr)
2784 Test the doxygen target that does trigger a full build
2787 if shutil.which(
"doxygen")
is None:
2788 self.skipTest(
"Missing doxygen")
2790 if shutil.which(
"bash")
is None:
2791 self.skipTest(
"Missing bash")
2793 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2795 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2796 for filename
in doxygen_files:
2797 file_path = os.sep.join([doc_folder, filename])
2798 if os.path.exists(file_path):
2799 os.remove(file_path)
2806 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2807 self.assertEqual(return_code, 0)
2809 self.assertIn(
"Built target doxygen", stdout)
2813 Test the doxygen target that doesn't trigger a full build
2816 if shutil.which(
"doxygen")
is None:
2817 self.skipTest(
"Missing doxygen")
2825 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2826 self.assertEqual(return_code, 0)
2828 self.assertIn(
"Built target doxygen-no-build", stdout)
2832 Test every individual target for Sphinx-based documentation
2835 if shutil.which(
"sphinx-build")
is None:
2836 self.skipTest(
"Missing sphinx")
2838 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2841 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2843 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2844 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2845 if os.path.exists(doc_build_folder):
2846 shutil.rmtree(doc_build_folder)
2847 if os.path.exists(doc_temp_folder):
2848 shutil.rmtree(doc_temp_folder)
2851 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2852 self.assertEqual(return_code, 0, target)
2854 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2857 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2858 self.assertTrue(os.path.exists(doc_build_folder))
2861 for build_type
in [
"latex",
"html",
"singlehtml"]:
2862 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2866 Test the documentation target that builds
2867 both doxygen and sphinx based documentation
2870 if shutil.which(
"doxygen")
is None:
2871 self.skipTest(
"Missing doxygen")
2872 if shutil.which(
"sphinx-build")
is None:
2873 self.skipTest(
"Missing sphinx")
2875 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2884 for target
in [
"manual",
"models",
"tutorial"]:
2885 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2886 if os.path.exists(doc_build_folder):
2887 shutil.rmtree(doc_build_folder)
2889 return_code, stdout, stderr =
run_ns3(
"docs all")
2890 self.assertEqual(return_code, 0)
2892 self.assertIn(
"Built target sphinx", stdout)
2894 self.assertIn(
"Built target doxygen", stdout)
2898 Try to set ownership of scratch-simulator from current user to root,
2899 and change execution permissions
2904 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2907 if sudo_password
is None:
2908 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2911 self.assertFalse(enable_sudo
is True)
2914 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2915 self.assertEqual(return_code, 0)
2916 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2918 scratch_simulator_path = list(
2919 filter(
lambda x: x
if "scratch-simulator" in x
else None, self.
ns3_executables)
2921 prev_fstat = os.stat(scratch_simulator_path)
2924 return_code, stdout, stderr =
run_ns3(
2925 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2927 self.assertEqual(return_code, 0)
2928 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2930 fstat = os.stat(scratch_simulator_path)
2936 likely_fuse_mount = (
2937 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2938 )
and prev_fstat.st_uid == 0
2940 if win32
or likely_fuse_mount:
2941 self.skipTest(
"Windows or likely a FUSE mount")
2944 self.assertEqual(fstat.st_uid, 0)
2946 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2950 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2951 self.assertEqual(return_code, 0)
2955 self.assertTrue(enable_sudo)
2959 if os.path.exists(executable):
2960 os.remove(executable)
2963 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2964 self.assertEqual(return_code, 0)
2967 self.assertIn(
"chown root", stdout)
2968 self.assertIn(
"chmod u+s", stdout)
2970 self.assertIn(os.path.basename(executable), stdout)
2973 fstat = os.stat(scratch_simulator_path)
2974 self.assertEqual(fstat.st_uid, 0)
2976 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2981 Check if command template is working
2986 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
2987 self.assertEqual(return_code0, 2)
2988 self.assertIn(
"argument --command-template: expected one argument", stderr0)
2990 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
2991 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
2992 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
2993 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
2994 for stderr
in [stderr1, stderr2, stderr3]:
2995 self.assertIn(
"not all arguments converted during string formatting", stderr)
2998 return_code4, stdout4, _ =
run_ns3(
2999 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
3001 return_code5, stdout5, _ =
run_ns3(
3002 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
3004 self.assertEqual((return_code4, return_code5), (0, 0))
3006 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3007 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3011 Check if all flavors of different argument passing to
3012 executable targets are working
3017 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3018 return_code1, stdout1, stderr1 =
run_ns3(
3019 'run sample-simulator --command-template="%s --help" --verbose'
3021 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3023 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3024 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3025 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3026 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3029 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3030 return_code1, stdout1, stderr1 =
run_ns3(
3031 'run sample-simulator --command-template="%s --help" --no-build'
3033 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3034 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3035 self.assertEqual(stdout0, stdout1)
3036 self.assertEqual(stdout1, stdout2)
3037 self.assertEqual(stderr0, stderr1)
3038 self.assertEqual(stderr1, stderr2)
3041 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3042 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3043 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3045 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3046 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3047 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3048 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3051 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3052 return_code, stdout, stderr =
run_ns3(cmd)
3053 self.assertEqual(return_code, 0)
3059 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3064 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3065 cmd1 =
"run sample-simulator --PrintTypeIds"
3067 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3068 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3069 self.assertEqual((return_code0, return_code1), (1, 1))
3070 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3071 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3075 Test if scratch simulator is executed through lldb
3078 if shutil.which(
"lldb")
is None:
3079 self.skipTest(
"Missing lldb")
3081 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3082 self.assertEqual(return_code, 0)
3084 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3085 self.assertEqual(return_code, 0)
3086 self.assertIn(
"scratch-simulator", stdout)
3087 self.assertIn(
"(lldb) target create", stdout)
3091 Test if CPM and Vcpkg package managers are working properly
3095 return_code, stdout, stderr =
run_ns3(
"clean")
3096 self.assertEqual(return_code, 0)
3099 if os.path.exists(
"vcpkg"):
3100 shutil.rmtree(
"vcpkg")
3103 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3105 if os.path.exists(destination_src):
3106 shutil.rmtree(destination_src)
3110 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3116 container.execute(
"apt-get update")
3117 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3122 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3123 self.skipTest(
"Armadillo is already installed")
3124 except DockerException
as e:
3128 return_code, stdout, stderr =
run_ns3(
"clean")
3129 self.assertEqual(return_code, 0)
3132 container.execute(
"apt-get install -y git")
3137 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3139 except DockerException
as e:
3144 container.execute(
"./ns3 build test-package-managers")
3145 except DockerException
as e:
3149 return_code, stdout, stderr =
run_ns3(
"clean")
3150 self.assertEqual(return_code, 0)
3152 if arch !=
"aarch64":
3154 container.execute(
"apt-get install -y zip unzip tar curl")
3157 container.execute(
"apt-get install -y pkg-config gfortran")
3161 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3162 except DockerException
as e:
3167 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3168 except DockerException
as e:
3173 container.execute(
"./ns3 build test-package-managers")
3174 except DockerException
as e:
3178 if os.path.exists(destination_src):
3179 shutil.rmtree(destination_src)
3183 Test if test.py and command-template handles empty spaces in executable paths correctly
3187 return_code, stdout, stderr =
run_ns3(
"clean")
3188 self.assertEqual(return_code, 0)
3192 container.execute(
"apt-get update")
3193 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3196 test_path =
"/path with empty spaces/ns-3-dev"
3198 container.execute(f
'mkdir -p "{test_path}"')
3199 container.execute(f
'cp -R ./ "{test_path}"')
3200 except DockerException
as e:
3206 './ns3 configure --enable-examples --enable-tests --filter-module-examples-and-tests="core;sixlowpan"',
3209 except DockerException
as e:
3214 container.execute(
"./test.py", workdir=test_path)
3215 except DockerException
as e:
3219 return_code, stdout, stderr =
run_ns3(
"clean")
3220 self.assertEqual(return_code, 0)
3225 ns-3 tests to control the quality of the repository over time
3230 Check if images in the docs are above a brightness threshold.
3231 This should prevent screenshots with dark UI themes.
3234 if shutil.which(
"convert")
is None:
3235 self.skipTest(
"Imagemagick was not found")
3237 from pathlib
import Path
3240 image_extensions = [
"png",
"jpg"]
3242 for extension
in image_extensions:
3243 images += list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3244 images += list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3247 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3251 brightness_threshold = 50
3252 for image
in images:
3253 brightness = subprocess.check_output(
3254 imagemagick_get_image_brightness.format(image=image).split()
3256 brightness = float(brightness.decode().strip(
"'\""))
3259 brightness_threshold,
3260 "Image darker than threshold (%d < %d): %s"
3261 % (brightness, brightness_threshold, image),
3266 Check if one of the log statements of examples/tests contains/exposes a bug.
3270 return_code, stdout, stderr =
run_ns3(
3271 'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
3273 self.assertEqual(return_code, 0)
3277 "test.py",
"", python=
True, env={
"TEST_LOGS":
"1"}
3279 self.assertEqual(return_code, 0)
3284 ns-3 complementary tests, allowed to fail, to help control
3285 the quality of the repository over time, by checking the
3286 state of URLs listed and more
3291 Test if all urls in source files are alive
3300 self.skipTest(
"Django URL validators are not available")
3307 urllib3.disable_warnings()
3310 self.skipTest(
"Requests library is not available")
3312 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3315 whitelisted_urls = {
3316 "https://gitlab.com/your-user-name/ns-3-dev",
3317 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3318 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3319 "https://www.nsnam.org/releases/ns-3-x",
3320 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3321 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3322 "https://ns-buildmaster.ee.washington.edu:8010/",
3324 "https://cmake.org/cmake/help/latest/manual/cmake-",
3325 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3327 "http://www.lysator.liu.se/~alla/dia/",
3329 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3330 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3331 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3332 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3333 "https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch",
3334 "http://www.nsnam.org/bugzilla/show_bug.cgi?id=",
3336 "http://www.research.att.com/info/kpv/",
3337 "http://www.research.att.com/~gsf/",
3338 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3339 "http://scan5.coverity.com/cgi-bin/upload.py",
3341 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3342 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3346 files_and_urls = set()
3348 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3349 for root, dirs, files
in os.walk(topdir):
3351 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3354 filepath = os.path.join(root, file)
3357 if not os.path.isfile(filepath):
3361 if file.endswith(
".svg"):
3365 with open(filepath,
"r", encoding=
"utf-8")
as f:
3366 matches = regex.findall(f.read())
3372 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3374 except UnicodeDecodeError:
3375 skipped_files.append(filepath)
3379 for url
in set(urls) - unique_urls - whitelisted_urls:
3380 unique_urls.add(url)
3381 files_and_urls.add((filepath, url))
3384 from django.core.exceptions
import ValidationError
3385 from django.core.validators
import URLValidator
3387 validate_url = URLValidator()
3391 "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"
3395 def test_file_url(args):
3396 test_filepath, test_url = args
3397 dead_link_msg =
None
3401 validate_url(test_url)
3402 except ValidationError:
3403 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3404 except Exception
as e:
3405 self.assertEqual(
False,
True, msg=e.__str__())
3407 if dead_link_msg
is not None:
3408 return dead_link_msg
3416 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3419 if response.status_code
in [200, 301]:
3420 dead_link_msg =
None
3425 if response.status_code
in [302, 308, 500, 503]:
3426 if response.reason.lower()
in [
3428 "moved temporarily",
3429 "permanent redirect",
3431 "service temporarily unavailable",
3433 dead_link_msg =
None
3437 dead_link_msg =
"%s: URL %s: returned code %d" % (
3440 response.status_code,
3442 except requests.exceptions.InvalidURL:
3443 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3444 except requests.exceptions.SSLError:
3445 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3446 except requests.exceptions.TooManyRedirects:
3447 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3448 except Exception
as e:
3450 error_msg = e.args[0].reason.__str__()
3451 except AttributeError:
3452 error_msg = e.args[0]
3453 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3459 return dead_link_msg
3462 from concurrent.futures
import ThreadPoolExecutor
3464 with ThreadPoolExecutor(max_workers=100)
as executor:
3465 dead_links = list(executor.map(test_file_url, list(files_and_urls)))
3468 dead_links = list(sorted(filter(
lambda x: x
is not None, dead_links)))
3469 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3473 Test if all tests can be executed without hitting major memory bugs
3476 return_code, stdout, stderr =
run_ns3(
3477 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3479 self.assertEqual(return_code, 0)
3481 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3482 self.assertEqual(test_return_code, 0)
3491 test_completeness = {
3493 NS3UnusedSourcesTestCase,
3497 NS3CommonSettingsTestCase,
3498 NS3ConfigureBuildProfileTestCase,
3499 NS3ConfigureTestCase,
3500 NS3BuildBaseTestCase,
3501 NS3ExpectedUseTestCase,
3504 NS3UnusedSourcesTestCase,
3506 NS3CommonSettingsTestCase,
3507 NS3ConfigureBuildProfileTestCase,
3508 NS3ConfigureTestCase,
3509 NS3BuildBaseTestCase,
3510 NS3ExpectedUseTestCase,
3511 NS3QualityControlTestCase,
3514 NS3DependenciesTestCase,
3515 NS3QualityControlThatCanFailTestCase,
3521 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3522 parser.add_argument(
3523 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3525 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3526 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3527 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3528 parser.add_argument(
"-f",
"--failfast", action=
"store_true", default=
False)
3529 args = parser.parse_args(sys.argv[1:])
3531 loader = unittest.TestLoader()
3532 suite = unittest.TestSuite()
3535 for testCase
in test_completeness[args.completeness]:
3536 suite.addTests(loader.loadTestsFromTestCase(testCase))
3541 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3543 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3544 tests_to_remove = set(tests) - set(tests_to_run)
3545 for test_to_remove
in tests_to_remove:
3546 suite._tests.remove(tests[test_to_remove])
3549 if args.resume_from_test_name:
3551 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3552 keys = list(tests.keys())
3554 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3555 suite._tests.remove(tests[keys[0]])
3559 ns3rc_script_bak = ns3rc_script +
".bak"
3560 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3561 shutil.move(ns3rc_script, ns3rc_script_bak)
3564 runner = unittest.TextTestRunner(failfast=args.failfast, verbosity=1
if args.quiet
else 2)
3568 if os.path.exists(ns3rc_script_bak):
3569 shutil.move(ns3rc_script_bak, ns3rc_script)
3572if __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.