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 libraries = glob.glob(lib_outdir +
"/*", recursive=
True)
148 return list(filter(
lambda x:
"scratch-nested-subdir-lib" not in x, libraries))
153 Gets a list of header files
154 @param outdir: path containing headers
155 @return list of headers.
157 return glob.glob(outdir +
"/**/*.h", recursive=
True)
162 Read interesting entries from the .lock-ns3 file
163 @param entry: entry to read from .lock-ns3
164 @return value of the requested entry.
167 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
168 exec(f.read(), globals(), values)
169 return values.get(entry,
None)
174 Check if tests are enabled in the .lock-ns3
182 Check if tests are enabled in the .lock-ns3
183 @return list of enabled modules (prefixed with 'ns3-').
190 Python-on-whales wrapper for Docker-based ns-3 tests
193 def __init__(self, currentTestCase: unittest.TestCase, containerName: str =
"ubuntu:latest"):
195 Create and start container with containerName in the current ns-3 directory
196 @param self: the current DockerContainerManager instance
197 @param currentTestCase: the test case instance creating the DockerContainerManager
198 @param containerName: name of the container image to be used
200 global DockerException
202 from python_on_whales
import docker
203 from python_on_whales.exceptions
import DockerException
204 except ModuleNotFoundError:
206 DockerException =
None
207 currentTestCase.skipTest(
"python-on-whales was not found")
210 with open(os.path.expanduser(
"~/.bashrc"),
"r", encoding=
"utf-8")
as f:
211 docker_settings = re.findall(
"(DOCKER_.*=.*)", f.read())
213 for setting
in docker_settings:
214 key, value = setting.split(
"=")
215 os.environ[key] = value
216 del setting, key, value
221 except DockerException
as e:
222 currentTestCase.skipTest(f
"python-on-whales returned:{e.__str__()}")
231 volumes=[(ns3_path,
"/ns-3-dev")],
235 def split_exec(docker_container, cmd):
236 return docker_container._execute(cmd.split(), workdir=
"/ns-3-dev")
243 Return the managed container when entiring the block "with DockerContainerManager() as container"
244 @param self: the current DockerContainerManager instance
245 @return container managed by DockerContainerManager.
251 Clean up the managed container at the end of the block "with DockerContainerManager() as container"
252 @param self: the current DockerContainerManager instance
253 @param exc_type: unused parameter
254 @param exc_val: unused parameter
255 @param exc_tb: unused parameter
264 ns-3 tests related to checking if source files were left behind, not being used by CMake
268 directory_and_files = {}
272 Scan all C++ source files and add them to a list based on their path
275 for root, dirs, files
in os.walk(ns3_path):
276 if "gitlab-ci-local" in root:
279 if name.endswith(
".cc"):
280 path = os.path.join(root, name)
281 directory = os.path.dirname(path)
288 Test if all example source files are being used in their respective CMakeLists.txt
291 unused_sources = set()
294 if os.sep +
"examples" not in example_directory:
298 if not os.path.exists(os.path.join(example_directory,
"CMakeLists.txt")):
303 os.path.join(example_directory,
"CMakeLists.txt"),
"r", encoding=
"utf-8"
305 cmake_contents = f.read()
310 if os.path.basename(file).replace(
".cc",
"")
not in cmake_contents:
311 unused_sources.add(file)
313 self.assertListEqual([], list(unused_sources))
317 Test if all module source files are being used in their respective CMakeLists.txt
320 unused_sources = set()
323 is_not_module =
not (
"src" in directory
or "contrib" in directory)
324 is_example = os.sep +
"examples" in directory
325 is_bindings = os.sep +
"bindings" in directory
327 if is_not_module
or is_bindings
or is_example:
332 cmake_path = os.path.join(directory,
"CMakeLists.txt")
333 while not os.path.exists(cmake_path):
334 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
335 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
338 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
339 cmake_contents = f.read()
343 if os.path.basename(file)
not in cmake_contents:
344 unused_sources.add(file)
348 "win32-system-wall-clock-ms.cc",
350 for exception
in exceptions:
351 for unused_source
in unused_sources:
352 if os.path.basename(unused_source) == exception:
353 unused_sources.remove(unused_source)
356 self.assertListEqual([], list(unused_sources))
360 Test if all utils source files are being used in their respective CMakeLists.txt
363 unused_sources = set()
366 is_module =
"src" in directory
or "contrib" in directory
367 if os.sep +
"utils" not in directory
or is_module:
372 cmake_path = os.path.join(directory,
"CMakeLists.txt")
373 while not os.path.exists(cmake_path):
374 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
375 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
378 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
379 cmake_contents = f.read()
383 if os.path.basename(file)
not in cmake_contents:
384 unused_sources.add(file)
386 self.assertListEqual([], list(unused_sources))
391 ns-3 tests related to dependencies
396 Checks if headers from different modules (src/A, contrib/B) that are included by
397 the current module (src/C) source files correspond to the list of linked modules
399 LIBRARIES_TO_LINK A (missing B)
403 headers_to_modules = {}
404 module_paths = glob.glob(ns3_path +
"/src/*/") + glob.glob(ns3_path +
"/contrib/*/")
406 for path
in module_paths:
408 cmake_path = os.path.join(path,
"CMakeLists.txt")
409 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
410 cmake_contents = f.readlines()
412 module_name = os.path.relpath(path, ns3_path)
413 module_name_nodir = module_name.replace(
"src/",
"").replace(
"contrib/",
"")
414 modules[module_name_nodir] = {
418 "included_headers": set(),
419 "included_libraries": set(),
423 for line
in cmake_contents:
424 source_file_path = re.findall(
r"\b(?:[^\s]+\.[ch]{1,2})\b", line.strip())
425 if not source_file_path:
427 source_file_path = source_file_path[0]
428 base_name = os.path.basename(source_file_path)
429 if not os.path.exists(os.path.join(path, source_file_path)):
432 if ".h" in source_file_path:
434 modules[module_name_nodir][
"headers"].add(base_name)
435 modules[module_name_nodir][
"sources"].add(base_name)
438 headers_to_modules[base_name] = module_name_nodir
440 if ".cc" in source_file_path:
442 modules[module_name_nodir][
"sources"].add(base_name)
444 if ".cc" in source_file_path
or ".h" in source_file_path:
446 source_file = os.path.join(ns3_path, module_name, source_file_path)
447 with open(source_file,
"r", encoding=
"utf-8")
as f:
448 source_contents = f.read()
449 modules[module_name_nodir][
"included_headers"].update(
451 lambda x: x.replace(
"ns3/",
""),
452 re.findall(
'#include.*["|<](.*)["|>]', source_contents),
458 modules[module_name_nodir][
"libraries"].update(
459 re.findall(
r"\${lib(.*?)}",
"".join(cmake_contents))
461 modules[module_name_nodir][
"libraries"] = list(
464 not in [
"raries_to_link", module_name_nodir, module_name_nodir +
"-obj"],
465 modules[module_name_nodir][
"libraries"],
470 all_project_headers = set(headers_to_modules.keys())
473 print(file=sys.stderr)
474 for module
in sorted(modules):
475 external_headers = modules[module][
"included_headers"].difference(all_project_headers)
476 project_headers_included = modules[module][
"included_headers"].difference(
479 modules[module][
"included_libraries"] = set(
480 [headers_to_modules[x]
for x
in project_headers_included]
481 ).difference({module})
483 diff = modules[module][
"included_libraries"].difference(modules[module][
"libraries"])
486 def recursive_check_dependencies(checked_module):
488 for module_to_link
in modules[checked_module][
"included_libraries"]:
489 modules[checked_module][
"included_libraries"] = set(
490 modules[checked_module][
"included_libraries"]
491 ) - set(modules[module_to_link][
"included_libraries"])
493 for module_to_link
in modules[checked_module][
"included_libraries"]:
494 recursive_check_dependencies(module_to_link)
497 def is_implicitly_linked(searched_module, current_module):
498 if len(modules[current_module][
"included_libraries"]) == 0:
500 if searched_module
in modules[current_module][
"included_libraries"]:
502 for module
in modules[current_module][
"included_libraries"]:
503 if is_implicitly_linked(searched_module, module):
507 from itertools
import combinations
509 implicitly_linked = set()
510 for dep1, dep2
in combinations(modules[checked_module][
"included_libraries"], 2):
511 if is_implicitly_linked(dep1, dep2):
512 implicitly_linked.add(dep1)
513 if is_implicitly_linked(dep2, dep1):
514 implicitly_linked.add(dep2)
516 modules[checked_module][
"included_libraries"] = (
517 set(modules[checked_module][
"included_libraries"]) - implicitly_linked
520 for module
in modules:
521 recursive_check_dependencies(module)
524 for module
in sorted(modules):
527 minimal_linking_set =
", ".join(modules[module][
"included_libraries"])
528 unnecessarily_linked =
", ".join(
529 set(modules[module][
"libraries"]) - set(modules[module][
"included_libraries"])
531 missing_linked =
", ".join(
532 set(modules[module][
"included_libraries"]) - set(modules[module][
"libraries"])
534 if unnecessarily_linked:
535 print(f
"Module '{module}' unnecessarily linked: {unnecessarily_linked}.")
537 print(f
"Module '{module}' missing linked: {missing_linked}.")
538 if unnecessarily_linked
or missing_linked:
539 print(f
"Module '{module}' minimal linking set: {minimal_linking_set}.")
540 self.assertTrue(
True)
545 ns-3 tests to check if the source code, whitespaces and CMake formatting
546 are according to the coding style
556 Import GitRepo and load the original diff state of the repository before the tests
559 if not NS3StyleTestCase.starting_diff:
560 if shutil.which(
"git")
is None:
561 self.skipTest(
"Git is not available")
567 self.skipTest(
"GitPython is not available")
570 repo = Repo(ns3_path)
571 except git.exc.InvalidGitRepositoryError:
572 self.skipTest(
"ns-3 directory does not contain a .git directory")
574 hcommit = repo.head.commit
575 NS3StyleTestCase.starting_diff = hcommit.diff(
None)
576 NS3StyleTestCase.repo = repo
578 if NS3StyleTestCase.starting_diff
is None:
579 self.skipTest(
"Unmet dependencies")
583 Check if there is any difference between tracked file after
584 applying cmake-format
588 for required_program
in [
"cmake",
"cmake-format"]:
589 if shutil.which(required_program)
is None:
590 self.skipTest(
"%s was not found" % required_program)
593 return_code, stdout, stderr =
run_ns3(
"configure")
594 self.assertEqual(return_code, 0)
597 return_code, stdout, stderr =
run_ns3(
"build cmake-format")
598 self.assertEqual(return_code, 0)
601 return_code, stdout, stderr =
run_ns3(
"clean")
602 self.assertEqual(return_code, 0)
605 new_diff = NS3StyleTestCase.repo.head.commit.diff(
None)
606 self.assertEqual(NS3StyleTestCase.starting_diff, new_diff)
611 ns3 tests related to generic options
616 Clean configuration/build artifacts before common commands
625 Test not passing any arguments to
628 return_code, stdout, stderr =
run_ns3(
"")
629 self.assertEqual(return_code, 1)
630 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
634 Test only passing --quiet argument to ns3
637 return_code, stdout, stderr =
run_ns3(
"--quiet")
638 self.assertEqual(return_code, 1)
639 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
643 Test only passing 'show config' argument to ns3
646 return_code, stdout, stderr =
run_ns3(
"show config")
647 self.assertEqual(return_code, 1)
648 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
652 Test only passing 'show profile' argument to ns3
655 return_code, stdout, stderr =
run_ns3(
"show profile")
656 self.assertEqual(return_code, 1)
657 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
661 Test only passing 'show version' argument to ns3
664 return_code, stdout, stderr =
run_ns3(
"show version")
665 self.assertEqual(return_code, 1)
666 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
671 ns3 tests related to build profiles
676 Clean configuration/build artifacts before testing configuration settings
688 return_code, stdout, stderr =
run_ns3(
689 'configure -G "{generator}" -d debug --enable-verbose'
691 self.assertEqual(return_code, 0)
692 self.assertIn(
"Build profile : debug", stdout)
693 self.assertIn(
"Build files have been written to", stdout)
696 return_code, stdout, stderr =
run_ns3(
"build core")
697 self.assertEqual(return_code, 0)
698 self.assertIn(
"Built target core", stdout)
701 self.assertGreater(len(libraries), 0)
702 self.assertIn(
"core-debug", libraries[0])
706 Test the release build
709 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d release')
710 self.assertEqual(return_code, 0)
711 self.assertIn(
"Build profile : release", stdout)
712 self.assertIn(
"Build files have been written to", stdout)
716 Test the optimized build
719 return_code, stdout, stderr =
run_ns3(
720 'configure -G "{generator}" -d optimized --enable-verbose'
722 self.assertEqual(return_code, 0)
723 self.assertIn(
"Build profile : optimized", stdout)
724 self.assertIn(
"Build files have been written to", stdout)
727 return_code, stdout, stderr =
run_ns3(
"build core")
728 self.assertEqual(return_code, 0)
729 self.assertIn(
"Built target core", stdout)
732 self.assertGreater(len(libraries), 0)
733 self.assertIn(
"core-optimized", libraries[0])
737 Test a build type with a typo
740 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d Optimized')
741 self.assertEqual(return_code, 2)
742 self.assertIn(
"invalid choice: 'Optimized'", stderr)
746 Test a build type with another typo
749 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d OPTIMIZED')
750 self.assertEqual(return_code, 2)
751 self.assertIn(
"invalid choice: 'OPTIMIZED'", stderr)
755 Replace settings set by default (e.g. ASSERT/LOGs enabled in debug builds and disabled in default ones)
758 return_code, _, _ =
run_ns3(
"clean")
759 self.assertEqual(return_code, 0)
761 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run -d debug')
762 self.assertEqual(return_code, 0)
764 "-DCMAKE_BUILD_TYPE=debug -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON -DNS3_NATIVE_OPTIMIZATIONS=OFF",
768 return_code, stdout, stderr =
run_ns3(
769 'configure -G "{generator}" --dry-run -d debug --disable-asserts --disable-logs --disable-werror'
771 self.assertEqual(return_code, 0)
773 "-DCMAKE_BUILD_TYPE=debug -DNS3_NATIVE_OPTIMIZATIONS=OFF -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF",
777 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run')
778 self.assertEqual(return_code, 0)
780 "-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF -DNS3_NATIVE_OPTIMIZATIONS=OFF",
784 return_code, stdout, stderr =
run_ns3(
785 'configure -G "{generator}" --dry-run --enable-asserts --enable-logs --enable-werror'
787 self.assertEqual(return_code, 0)
789 "-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",
796 Generic test case with basic function inherited by more complex tests.
801 Check if configuration for release mode worked normally
802 @param return_code: return code from CMake
803 @param stdout: output from CMake.
804 @param stderr: error from CMake.
807 self.assertEqual(return_code, 0)
808 self.assertIn(
"Build profile : release", stdout)
809 self.assertIn(
"Build files have been written to", stdout)
810 self.assertNotIn(
"uninitialized variable", stderr)
814 Clean configuration/build artifacts before testing configuration and build settings
815 After configuring the build as release,
816 check if configuration worked and check expected output files.
821 if os.path.exists(ns3rc_script):
822 os.remove(ns3rc_script)
826 return_code, stdout, stderr =
run_ns3(
827 'configure -G "{generator}" -d release --enable-verbose'
829 self.
config_ok(return_code, stdout, stderr)
832 self.assertTrue(os.path.exists(ns3_lock_filename))
837 self.assertTrue(os.path.exists(ns3_lock_filename))
844 Test ns3 configuration options
849 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
856 Test enabling and disabling examples
859 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
862 self.
config_ok(return_code, stdout, stderr)
869 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
872 self.
config_ok(return_code, stdout, stderr)
879 Test enabling and disabling tests
883 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-tests')
884 self.
config_ok(return_code, stdout, stderr)
887 return_code, stdout, stderr =
run_ns3(
"build core-test")
890 self.assertEqual(return_code, 0)
891 self.assertIn(
"Built target core-test", stdout)
894 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-tests')
895 self.
config_ok(return_code, stdout, stderr)
898 return_code, stdout, stderr =
run_ns3(
"build core-test")
901 self.assertEqual(return_code, 1)
902 self.assertIn(
"Target to build does not exist: core-test", stdout)
906 Test enabling specific modules
910 return_code, stdout, stderr =
run_ns3(
911 "configure -G \"{generator}\" --enable-modules='network;wifi'"
913 self.
config_ok(return_code, stdout, stderr)
919 self.assertIn(
"ns3-network", enabled_modules)
920 self.assertIn(
"ns3-wifi", enabled_modules)
923 return_code, stdout, stderr =
run_ns3(
924 "configure -G \"{generator}\" --enable-modules='core'"
926 self.
config_ok(return_code, stdout, stderr)
930 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
931 self.
config_ok(return_code, stdout, stderr)
938 Test disabling specific modules
942 return_code, stdout, stderr =
run_ns3(
943 "configure -G \"{generator}\" --disable-modules='lte;wifi'"
945 self.
config_ok(return_code, stdout, stderr)
949 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
950 self.assertNotIn(
"ns3-lte", enabled_modules)
951 self.assertNotIn(
"ns3-wifi", enabled_modules)
954 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
955 self.
config_ok(return_code, stdout, stderr)
962 Test enabling comma-separated (waf-style) examples
966 return_code, stdout, stderr =
run_ns3(
967 "configure -G \"{generator}\" --enable-modules='network,wifi'"
969 self.
config_ok(return_code, stdout, stderr)
974 self.assertIn(
"ns3-network", enabled_modules)
975 self.assertIn(
"ns3-wifi", enabled_modules)
978 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
979 self.
config_ok(return_code, stdout, stderr)
986 Test disabling comma-separated (waf-style) examples
990 return_code, stdout, stderr =
run_ns3(
991 "configure -G \"{generator}\" --disable-modules='lte,mpi'"
993 self.
config_ok(return_code, stdout, stderr)
997 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
998 self.assertNotIn(
"ns3-lte", enabled_modules)
999 self.assertNotIn(
"ns3-mpi", enabled_modules)
1002 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
1003 self.
config_ok(return_code, stdout, stderr)
1010 Test loading settings from the ns3rc config file
1016 ns3rc_python_template =
"# ! /usr/bin/env python\
1018 # A list of the modules that will be enabled when ns-3 is run.\
1019 # Modules that depend on the listed modules will be enabled also.\
1021 # All modules can be enabled by choosing 'all_modules'.\
1022 modules_enabled = [{modules}]\
1024 # Set this equal to true if you want examples to be run.\
1025 examples_enabled = {examples}\
1027 # Set this equal to true if you want tests to be run.\
1028 tests_enabled = {tests}\
1032 ns3rc_cmake_template =
"set(ns3rc_tests_enabled {tests})\
1033 \nset(ns3rc_examples_enabled {examples})\
1034 \nset(ns3rc_enabled_modules {modules})\
1038 ns3rc_templates = {
"python": ns3rc_python_template,
"cmake": ns3rc_cmake_template}
1040 def __init__(self, type_ns3rc):
1044 def format(self, **args):
1046 if self.
type ==
"cmake":
1048 args[
"modules"].replace(
"'",
"").replace(
'"',
"").replace(
",",
" ")
1050 args[
"examples"] =
"ON" if args[
"examples"] ==
"True" else "OFF"
1051 args[
"tests"] =
"ON" if args[
"tests"] ==
"True" else "OFF"
1053 formatted_string = ns3rc_str.ns3rc_templates[self.
type].format(**args)
1056 return formatted_string
1060 return ns3rc_str.ns3rc_templates.keys()
1062 for ns3rc_type
in ns3rc_str.types():
1064 ns3rc_template = ns3rc_str(ns3rc_type)
1067 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1068 f.write(ns3rc_template.format(modules=
"'lte'", examples=
"False", tests=
"True"))
1072 return_code, stdout, stderr =
run_ns3(
1073 'configure -G "{generator}" -d release --enable-verbose'
1075 self.
config_ok(return_code, stdout, stderr)
1080 self.assertIn(
"ns3-lte", enabled_modules)
1082 self.assertLessEqual(
1087 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1088 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
1091 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1092 self.
config_ok(return_code, stdout, stderr)
1097 self.assertIn(
"ns3-wifi", enabled_modules)
1102 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1104 ns3rc_template.format(
1105 modules=
"'core','network'", examples=
"True", tests=
"False"
1110 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1111 self.
config_ok(return_code, stdout, stderr)
1116 self.assertIn(
"ns3-core", enabled_modules)
1117 self.assertIn(
"ns3-network", enabled_modules)
1123 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1124 if ns3rc_type ==
"python":
1126 ns3rc_template.format(
1127 modules=
"""'core', #comment
1131 'network', 'internet','wifi'""",
1138 ns3rc_template.format(
1139 modules=
"'core', 'lte', 'network', 'internet', 'wifi'",
1145 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1146 self.
config_ok(return_code, stdout, stderr)
1151 self.assertIn(
"ns3-core", enabled_modules)
1152 self.assertIn(
"ns3-internet", enabled_modules)
1153 self.assertIn(
"ns3-lte", enabled_modules)
1154 self.assertIn(
"ns3-wifi", enabled_modules)
1159 os.remove(ns3rc_script)
1162 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1163 self.
config_ok(return_code, stdout, stderr)
1172 Test dry-run (printing commands to be executed instead of running them)
1178 for positional_command
in [
"configure",
"build",
"clean"]:
1179 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
1180 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
1182 self.assertEqual(return_code, return_code1)
1183 self.assertEqual(stdout, stdout1)
1184 self.assertEqual(stderr, stderr1)
1189 run_ns3(
'configure -G "{generator}" -d release --enable-verbose')
1190 run_ns3(
"build scratch-simulator")
1193 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
1194 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
1195 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
1196 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
1199 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
1200 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
1204 if "scratch-simulator" in program
and "subdir" not in program:
1205 scratch_path = program
1211 self.assertIn(scratch_path, stdout0)
1215 self.assertIn(
"Built target", stdout1)
1216 self.assertNotIn(scratch_path, stdout1)
1219 self.assertIn(
"The following commands would be executed:", stdout2)
1220 self.assertIn(scratch_path, stdout2)
1223 self.assertNotIn(
"Finished executing the following commands:", stdout3)
1224 self.assertNotIn(scratch_path, stdout3)
1228 Test if ns3 is propagating back the return code from the executables called with the run command
1232 return_code, _, _ =
run_ns3(
"clean")
1233 self.assertEqual(return_code, 0)
1235 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-examples --enable-tests')
1236 self.assertEqual(return_code, 0)
1239 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
1240 self.assertEqual(return_code, 0)
1243 return_code, stdout, stderr =
run_ns3(
1244 'run "test-runner --test-name=command-line" --no-build'
1246 self.assertEqual(return_code, 0)
1249 return_code, stdout, stderr =
run_ns3(
1250 'run "test-runner --test-name=command-line" --no-build',
1251 env={
"NS_COMMANDLINE_INTROSPECTION":
".."},
1253 self.assertNotEqual(return_code, 0)
1256 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
1257 with open(sigsegv_example,
"w", encoding=
"utf-8")
as f:
1259 int main (int argc, char *argv[])
1261 char *s = "hello world"; *s = 'H';
1265 return_code, stdout, stderr =
run_ns3(
"run sigsegv")
1267 self.assertEqual(return_code, 4294967295)
1268 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1270 self.assertEqual(return_code, 245)
1271 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1274 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1275 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1277 #include "ns3/core-module.h"
1279 using namespace ns3;
1280 int main (int argc, char *argv[])
1286 return_code, stdout, stderr =
run_ns3(
"run abort")
1288 self.assertNotEqual(return_code, 0)
1289 self.assertIn(
"abort-default.exe' returned non-zero exit status", stdout)
1291 self.assertEqual(return_code, 250)
1292 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
1294 os.remove(sigsegv_example)
1295 os.remove(abort_example)
1299 Test passing 'show config' argument to ns3 to get the configuration table
1302 return_code, stdout, stderr =
run_ns3(
"show config")
1303 self.assertEqual(return_code, 0)
1304 self.assertIn(
"Summary of ns-3 settings", stdout)
1308 Test passing 'show profile' argument to ns3 to get the build profile
1311 return_code, stdout, stderr =
run_ns3(
"show profile")
1312 self.assertEqual(return_code, 0)
1313 self.assertIn(
"Build profile: release", stdout)
1317 Test passing 'show version' argument to ns3 to get the build version
1320 if shutil.which(
"git")
is None:
1321 self.skipTest(
"git is not available")
1323 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-build-version')
1324 self.assertEqual(return_code, 0)
1326 return_code, stdout, stderr =
run_ns3(
"show version")
1327 self.assertEqual(return_code, 0)
1328 self.assertIn(
"ns-3 version:", stdout)
1332 Test if CMake target names for scratches and ns3 shortcuts
1333 are working correctly
1340 "scratch/subdir1/main.cc",
1341 "scratch/subdir2/main.cc",
1342 "scratch/main.test.dots.in.name.cc",
1344 backup_files = [
"scratch/.main.cc"]
1347 for path
in test_files + backup_files:
1348 filepath = os.path.join(ns3_path, path)
1349 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
1350 with open(filepath,
"w", encoding=
"utf-8")
as f:
1352 f.write(
"int main (int argc, char *argv[]){}")
1361 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1362 self.assertEqual(return_code, 1)
1365 empty =
"scratch/empty.cc"
1367 test_files.remove(empty)
1368 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1369 self.assertEqual(return_code, 0)
1372 for path
in test_files + backup_files:
1373 path = path.replace(
".cc",
"")
1376 "--build . --target %s -j %d" % (path.replace(
"/",
"_"), num_threads),
1377 cwd=os.path.join(ns3_path,
"cmake-cache"),
1379 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
1380 if "main" in path
and ".main" not in path:
1381 self.assertEqual(return_code1, 0)
1382 self.assertEqual(return_code2, 0)
1384 self.assertEqual(return_code1, 2)
1385 self.assertEqual(return_code2, 1)
1388 for path
in test_files:
1389 path = path.replace(
".cc",
"")
1390 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
1392 self.assertEqual(return_code, 0)
1394 self.assertEqual(return_code, 1)
1398 container.execute(
"apt-get update")
1399 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
1402 "./ns3 configure --enable-modules=core,network,internet -- -DCMAKE_CXX_COMPILER=/usr/bin/g++"
1404 except DockerException
as e:
1406 for path
in test_files:
1407 path = path.replace(
".cc",
"")
1409 container.execute(f
"./ns3 run {path}")
1410 except DockerException
as e:
1416 for path
in test_files + backup_files:
1417 source_absolute_path = os.path.join(ns3_path, path)
1418 os.remove(source_absolute_path)
1419 if "empty" in path
or ".main" in path:
1421 filename = os.path.basename(path).replace(
".cc",
"")
1422 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
1423 if os.path.exists(executable_absolute_path):
1424 executable_name = list(
1425 filter(
lambda x: filename
in x, os.listdir(executable_absolute_path))
1428 os.remove(os.path.join(executable_absolute_path, executable_name))
1429 if not os.listdir(os.path.dirname(path)):
1430 os.rmdir(os.path.dirname(source_absolute_path))
1432 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1433 self.assertEqual(return_code, 0)
1437 Test if ns3 is inserting additional arguments by MPICH and OpenMPI to run on the CI
1441 if shutil.which(
"mpiexec")
is None or win32:
1442 self.skipTest(
"Mpi is not available")
1444 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1445 self.assertEqual(return_code, 0)
1449 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
1450 self.assertEqual(return_code, 0)
1453 sample_simulator_path = list(filter(
lambda x:
"sample-simulator" in x, executables))[0]
1455 mpi_command =
'--dry-run run sample-simulator --command-template="mpiexec -np 2 %s"'
1456 non_mpi_command =
'--dry-run run sample-simulator --command-template="echo %s"'
1459 return_code, stdout, stderr =
run_ns3(mpi_command)
1460 self.assertEqual(return_code, 0)
1461 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1464 return_code, stdout, stderr =
run_ns3(mpi_command)
1465 self.assertEqual(return_code, 0)
1466 if os.getenv(
"USER",
"") ==
"root":
1467 if shutil.which(
"ompi_info"):
1469 "mpiexec --allow-run-as-root --oversubscribe -np 2 %s" % sample_simulator_path,
1474 "mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout
1477 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1480 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1481 self.assertEqual(return_code, 0)
1482 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1485 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1486 self.assertEqual(return_code, 0)
1487 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1489 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1490 self.assertEqual(return_code, 0)
1494 Test if CMake and ns3 fail in the expected ways when:
1495 - examples from modules or general examples fail if they depend on a
1496 library with a name shorter than 4 characters or are disabled when
1497 a library is nonexistent
1498 - a module library passes the configuration but fails to build due to
1502 os.makedirs(
"contrib/borked", exist_ok=
True)
1503 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1506 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1508 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1509 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1513 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1514 LIBRARIES_TO_LINK ${libcore} %s
1516 """ % invalid_or_nonexistent_library)
1518 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1519 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1520 self.assertEqual(return_code, 0)
1521 elif invalid_or_nonexistent_library
in [
"lib"]:
1522 self.assertEqual(return_code, 1)
1523 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1527 return_code, stdout, stderr =
run_ns3(
"build borked")
1528 if invalid_or_nonexistent_library
in [
""]:
1529 self.assertEqual(return_code, 0)
1530 elif invalid_or_nonexistent_library
in [
"lib"]:
1531 self.assertEqual(return_code, 2)
1532 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1533 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1534 self.assertEqual(return_code, 2)
1535 if "lld" in stdout + stderr:
1537 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1539 elif "mold" in stdout + stderr:
1540 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1543 "library not found for -l%s" % invalid_or_nonexistent_library, stderr
1546 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1554 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1558 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1559 LIBRARIES_TO_LINK ${libcore}
1562 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1563 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1567 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1568 LIBRARIES_TO_LINK ${libborked} %s
1570 """ % invalid_or_nonexistent_library)
1572 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1573 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1574 self.assertEqual(return_code, 0)
1575 elif invalid_or_nonexistent_library
in [
"lib"]:
1576 self.assertEqual(return_code, 1)
1577 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1581 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1582 if invalid_or_nonexistent_library
in [
""]:
1583 self.assertEqual(return_code, 0)
1584 elif invalid_or_nonexistent_library
in [
"libf"]:
1585 self.assertEqual(return_code, 2)
1586 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1587 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1588 self.assertEqual(return_code, 1)
1589 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1593 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1597 Test if CMake can properly handle modules containing "lib",
1598 which is used internally as a prefix for module libraries
1602 os.makedirs(
"contrib/calibre", exist_ok=
True)
1603 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1606 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1608 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1612 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1613 LIBRARIES_TO_LINK ${libcore}
1617 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1620 self.assertEqual(return_code, 0)
1623 self.assertIn(
"calibre", stdout)
1627 self.assertNotIn(
"care", stdout)
1629 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1633 return_code, stdout, stderr =
run_ns3(
"build calibre")
1634 self.assertEqual(return_code, 0)
1637 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1641 Test if CMake performance tracing works and produces the
1642 cmake_performance_trace.log file
1645 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1646 if os.path.exists(cmake_performance_trace_log):
1647 os.remove(cmake_performance_trace_log)
1649 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1650 self.assertEqual(return_code, 0)
1652 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1655 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1658 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1662 Check if ENABLE_BUILD_VERSION and version.cache are working
1670 container.execute(
"apt-get update")
1671 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1674 container.execute(
"./ns3 clean")
1677 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1680 if os.path.exists(version_cache_file):
1681 os.remove(version_cache_file)
1685 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1686 except DockerException:
1688 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1691 version_cache_contents = (
1692 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1693 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1694 "VERSION_DIRTY_FLAG = '0'\n"
1695 "VERSION_MAJOR = '3'\n"
1696 "VERSION_MINOR = '0'\n"
1697 "VERSION_PATCH = '0'\n"
1698 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1699 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1700 "VERSION_TAG_DISTANCE = '0'\n"
1701 "VERSION_BUILD_PROFILE = 'debug'\n"
1703 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1704 version.write(version_cache_contents)
1707 container.execute(
"./ns3 clean")
1708 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1709 container.execute(
"./ns3 build core")
1710 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1713 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1714 self.assertEqual(version.read(), version_cache_contents)
1719 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1721 container.execute(
"apt-get install -y git")
1722 container.execute(
"./ns3 clean")
1723 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1724 container.execute(
"./ns3 build core")
1725 except DockerException:
1727 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1728 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1731 container.execute(
"./ns3 clean")
1732 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1733 container.execute(
"./ns3 build core")
1734 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1735 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1736 self.assertNotEqual(version.read(), version_cache_contents)
1739 if os.path.exists(version_cache_file):
1740 os.remove(version_cache_file)
1744 Test filtering in examples and tests from specific modules
1748 return_code, stdout, stderr =
run_ns3(
1749 'configure -G "{generator}" --enable-examples --enable-tests'
1751 self.
config_ok(return_code, stdout, stderr)
1756 return_code, stdout, stderr =
run_ns3(
1757 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1759 self.
config_ok(return_code, stdout, stderr)
1765 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1767 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1770 return_code, stdout, stderr =
run_ns3(
1771 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1773 self.
config_ok(return_code, stdout, stderr)
1781 return_code, stdout, stderr =
run_ns3(
1782 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1784 self.
config_ok(return_code, stdout, stderr)
1792 Check if fast linkers LLD and Mold are correctly found and configured
1799 container.execute(
"apt-get update")
1800 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1803 container.execute(
"./ns3 configure -G Ninja")
1806 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1808 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1810 self.assertIn(
"-fuse-ld=lld", f.read())
1814 container.execute(
"./ns3 build core")
1815 except DockerException:
1816 self.assertTrue(
False,
"Build with lld failed")
1819 if not os.path.exists(f
"./mold-1.4.2-{arch}-linux.tar.gz"):
1821 f
"wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch}-linux.tar.gz"
1824 f
"tar xzfC mold-1.4.2-{arch}-linux.tar.gz /usr/local --strip-components=1"
1829 container.execute(
"./ns3 configure -G Ninja")
1832 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1834 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1836 self.assertIn(
"-fuse-ld=mold", f.read())
1840 container.execute(
"./ns3 build core")
1841 except DockerException:
1842 self.assertTrue(
False,
"Build with mold failed")
1845 os.remove(f
"./mold-1.4.2-{arch}-linux.tar.gz")
1848 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1851 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1853 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1855 self.assertNotIn(
"-fuse-ld=mold", f.read())
1859 Check if NS3_CLANG_TIMETRACE feature is working
1860 Clang's -ftime-trace plus ClangAnalyzer report
1866 container.execute(
"apt-get update")
1867 container.execute(
"apt-get install -y python3 ninja-build cmake clang-18")
1872 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1874 except DockerException
as e:
1875 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1877 container.execute(
"apt-get install -y git")
1882 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1884 except DockerException
as e:
1885 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1888 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1889 if os.path.exists(time_trace_report_path):
1890 os.remove(time_trace_report_path)
1894 container.execute(
"./ns3 build timeTraceReport")
1895 except DockerException
as e:
1896 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1899 self.assertTrue(os.path.exists(time_trace_report_path))
1903 container.execute(
"apt-get install -y g++")
1904 container.execute(
"apt-get remove -y clang-18")
1908 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1911 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1913 except DockerException
as e:
1914 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1918 Check if NS3_NINJA_TRACE feature is working
1919 Ninja's .ninja_log conversion to about://tracing
1920 json format conversion with Ninjatracing
1926 container.execute(
"apt-get update")
1927 container.execute(
"apt-get remove -y g++")
1928 container.execute(
"apt-get install -y python3 cmake g++-11 clang-18")
1933 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1935 except DockerException
as e:
1936 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1941 container.execute(
"apt-get install -y ninja-build")
1945 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1947 except DockerException
as e:
1948 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1950 container.execute(
"apt-get install -y git")
1954 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1956 except DockerException
as e:
1957 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1960 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1961 if os.path.exists(ninja_trace_path):
1962 os.remove(ninja_trace_path)
1965 container.execute(
"./ns3 build core")
1969 container.execute(
"./ns3 build ninjaTrace")
1970 except DockerException
as e:
1971 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1974 self.assertTrue(os.path.exists(ninja_trace_path))
1975 trace_size = os.stat(ninja_trace_path).st_size
1976 os.remove(ninja_trace_path)
1983 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1985 except DockerException
as e:
1986 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
1989 container.execute(
"./ns3 build core")
1993 container.execute(
"./ns3 build ninjaTrace")
1994 except DockerException
as e:
1995 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1997 self.assertTrue(os.path.exists(ninja_trace_path))
1998 timetrace_size = os.stat(ninja_trace_path).st_size
1999 os.remove(ninja_trace_path)
2002 self.assertGreater(timetrace_size, trace_size)
2006 Check if precompiled headers are being enabled correctly.
2016 container.execute(
"apt-get update")
2017 container.execute(
"apt-get install -y python3 cmake ccache g++")
2019 container.execute(
"./ns3 configure")
2020 except DockerException
as e:
2021 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2025 Check for regressions in test object build.
2028 return_code, stdout, stderr =
run_ns3(
"configure")
2029 self.assertEqual(return_code, 0)
2031 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2032 self.assertFalse(os.path.exists(test_module_cache))
2034 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2035 self.assertEqual(return_code, 0)
2036 self.assertTrue(os.path.exists(test_module_cache))
2040 Check for regressions in a bare ns-3 configuration.
2047 container.execute(
"apt-get update")
2048 container.execute(
"apt-get install -y python3 cmake g++")
2052 stdout = container.execute(
"./ns3 configure -d release")
2053 except DockerException
as e:
2055 self.
config_ok(return_code, stdout, stdout)
2062 Tests ns3 regarding building the project
2067 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2076 Try building the core library
2079 return_code, stdout, stderr =
run_ns3(
"build core")
2080 self.assertEqual(return_code, 0)
2081 self.assertIn(
"Built target core", stdout)
2085 Try building core-test library without tests enabled
2089 return_code, stdout, stderr =
run_ns3(
"build core-test")
2090 self.assertEqual(return_code, 1)
2091 self.assertIn(
"Target to build does not exist: core-test", stdout)
2095 Try building the project:
2098 return_code, stdout, stderr =
run_ns3(
"build")
2099 self.assertEqual(return_code, 0)
2100 self.assertIn(
"Built target", stdout)
2102 self.assertTrue(os.path.exists(program), program)
2103 self.assertIn(cmake_build_project_command, stdout)
2107 Try hiding task lines
2110 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2111 self.assertEqual(return_code, 0)
2112 self.assertIn(cmake_build_project_command, stdout)
2116 Try removing an essential file to break the build
2120 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2121 attribute_cc_bak_path = attribute_cc_path +
".bak"
2122 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2125 return_code, stdout, stderr =
run_ns3(
"build")
2126 self.assertNotEqual(return_code, 0)
2129 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2132 return_code, stdout, stderr =
run_ns3(
"build")
2133 self.assertEqual(return_code, 0)
2137 Test if changing the version file affects the library names
2143 version_file = os.sep.join([ns3_path,
"VERSION"])
2144 with open(version_file,
"w", encoding=
"utf-8")
as f:
2148 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2149 self.
config_ok(return_code, stdout, stderr)
2152 return_code, stdout, stderr =
run_ns3(
"build")
2153 self.assertEqual(return_code, 0)
2154 self.assertIn(
"Built target", stdout)
2160 for program
in new_programs:
2161 self.assertTrue(os.path.exists(program))
2168 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2169 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2170 for library
in new_libraries:
2171 self.assertNotIn(
"libns3-dev", library)
2172 self.assertIn(
"libns3-00", library)
2173 self.assertTrue(os.path.exists(library))
2176 with open(version_file,
"w", encoding=
"utf-8")
as f:
2181 Try setting a different output directory and if everything is
2182 in the right place and still working correctly
2187 return_code, stdout, stderr =
run_ns3(
"build")
2188 self.assertEqual(return_code, 0)
2203 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2204 relative_path = os.sep.join([
"build",
"release"])
2205 for different_out_dir
in [absolute_path, relative_path]:
2206 return_code, stdout, stderr =
run_ns3(
2207 'configure -G "{generator}" --out=%s' % different_out_dir
2209 self.
config_ok(return_code, stdout, stderr)
2211 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2220 for program
in new_programs:
2221 self.assertTrue(os.path.exists(program))
2225 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2226 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2227 for library
in new_libraries:
2228 self.assertTrue(os.path.exists(library))
2231 shutil.rmtree(absolute_path)
2234 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2235 self.
config_ok(return_code, stdout, stderr)
2237 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2246 for program
in new_programs:
2247 self.assertTrue(os.path.exists(program))
2252 for library
in libraries:
2253 self.assertTrue(os.path.exists(library))
2257 Tries setting a ns3 version, then installing it.
2258 After that, tries searching for ns-3 with CMake's find_package(ns3).
2259 Finally, tries using core library in a 3rd-party project
2264 for library
in libraries:
2268 version_file = os.sep.join([ns3_path,
"VERSION"])
2269 with open(version_file,
"w", encoding=
"utf-8")
as f:
2273 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2274 return_code, stdout, stderr =
run_ns3(
2275 'configure -G "{generator}" --prefix=%s' % install_prefix
2277 self.
config_ok(return_code, stdout, stderr)
2288 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2289 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2293 installed_libraries_list =
";".join(installed_libraries)
2294 for library
in libraries:
2295 library_name = os.path.basename(library)
2296 self.assertIn(library_name, installed_libraries_list)
2300 missing_headers = list(
2301 set([os.path.basename(x)
for x
in headers])
2302 - (set([os.path.basename(x)
for x
in installed_headers]))
2304 self.assertEqual(len(missing_headers), 0)
2307 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2308 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2310 #include <ns3/core-module.h>
2311 using namespace ns3;
2314 Simulator::Stop (Seconds (1.0));
2316 Simulator::Destroy ();
2324 for version
in [
"",
"3.01",
"3.00"]:
2325 ns3_import_methods = []
2328 cmake_find_package_import =
"""
2329 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2330 find_package(ns3 {version} COMPONENTS core)
2331 target_link_libraries(test PRIVATE ns3::core)
2332 """.format(lib=(
"lib64" if lib64
else "lib"), version=version)
2333 ns3_import_methods.append(cmake_find_package_import)
2336 pkgconfig_import =
"""
2337 list(APPEND CMAKE_PREFIX_PATH ./)
2338 include(FindPkgConfig)
2339 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2340 target_link_libraries(test PUBLIC PkgConfig::ns3)
2342 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2344 if shutil.which(
"pkg-config"):
2345 ns3_import_methods.append(pkgconfig_import)
2348 for import_method
in ns3_import_methods:
2349 test_cmake_project =
"""
2350 cmake_minimum_required(VERSION 3.20..3.20)
2351 project(ns3_consumer CXX)
2352 set(CMAKE_CXX_STANDARD 23)
2353 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2354 add_executable(test main.cpp)
2357 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2358 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2359 f.write(test_cmake_project)
2362 cmake = shutil.which(
"cmake")
2365 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2366 generator=platform_makefiles
2371 if version ==
"3.00":
2372 self.assertEqual(return_code, 1)
2373 if import_method == cmake_find_package_import:
2375 'Could not find a configuration file for package "ns3" that is compatible',
2376 stderr.replace(
"\n",
""),
2378 elif import_method == pkgconfig_import:
2379 self.assertIn(
"not found", stderr.replace(
"\n",
""))
2381 raise Exception(
"Unknown import type")
2383 self.assertEqual(return_code, 0)
2384 self.assertIn(
"Build files", stdout)
2387 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2389 if version ==
"3.00":
2390 self.assertEqual(return_code, 2, msg=stdout + stderr)
2391 self.assertGreater(len(stderr), 0)
2393 self.assertEqual(return_code, 0)
2394 self.assertIn(
"Built target", stdout)
2398 test_program = os.path.join(install_prefix,
"test.exe")
2399 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2401 "PATH": env_sep.join(
2402 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2406 test_program =
"./test"
2409 test_program,
"", cwd=install_prefix, env=env
2411 self.assertEqual(return_code, 0)
2414 return_code, stdout, stderr =
run_ns3(
"uninstall")
2415 self.assertIn(
"Built target uninstall", stdout)
2418 os.remove(version_file)
2419 with open(version_file,
"w", encoding=
"utf-8")
as f:
2424 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2429 "scratch/scratch-simulator":
"scratch-simulator",
2430 "scratch/scratch-simulator.cc":
"scratch-simulator",
2431 "scratch-simulator":
"scratch-simulator",
2432 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2433 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2434 "scratch-subdir":
"subdir_scratch-subdir",
2436 for target_to_run, target_cmake
in targets.items():
2438 build_line =
"target scratch_%s" % target_cmake
2439 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2440 self.assertEqual(return_code, 0)
2441 self.assertIn(build_line, stdout)
2444 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2445 self.assertEqual(return_code, 0)
2446 self.assertIn(build_line, stdout)
2447 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2448 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2452 Test if ns3 can alert correctly in case a shortcut collision happens
2457 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2458 self.assertEqual(return_code, 0)
2461 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2464 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2465 self.assertEqual(return_code, 0)
2468 return_code, stdout, stderr =
run_ns3(
"build second")
2469 self.assertEqual(return_code, 1)
2471 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2472 stdout.replace(os.sep,
"/"),
2476 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2477 self.assertEqual(return_code, 0)
2481 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2482 self.assertEqual(return_code, 0)
2486 return_code, stdout, stderr =
run_ns3(
"run second")
2487 self.assertEqual(return_code, 1)
2489 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2490 stdout.replace(os.sep,
"/"),
2494 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2495 self.assertEqual(return_code, 0)
2498 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2499 self.assertEqual(return_code, 0)
2502 os.remove(
"./scratch/second.cc")
2506 Test if we can build a static ns-3 library and link it to static programs
2509 if (
not win32)
and (arch ==
"aarch64"):
2510 if platform.libc_ver()[0] ==
"glibc":
2511 from packaging.version
import Version
2513 if Version(platform.libc_ver()[1]) < Version(
"2.37"):
2515 "Static linking on ARM64 requires glibc 2.37 where fPIC was enabled (fpic is limited in number of GOT entries)"
2519 return_code, stdout, stderr =
run_ns3(
2520 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2526 self.assertEqual(return_code, 1)
2527 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2530 self.assertEqual(return_code, 0)
2533 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2534 self.assertEqual(return_code, 0)
2535 self.assertIn(
"Built target", stdout)
2541 Test if we can use python bindings
2546 except ModuleNotFoundError:
2547 self.skipTest(
"Cppyy was not found")
2550 return_code, stdout, stderr =
run_ns3(
2551 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2555 self.assertEqual(return_code, 0)
2558 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2559 self.assertEqual(return_code, 0)
2562 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2563 self.assertEqual(return_code, 0)
2567 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2569 self.assertEqual(return_code, 0)
2573 Test if we had regressions with brite, click and openflow modules
2574 that depend on homonymous libraries
2577 if shutil.which(
"git")
is None:
2578 self.skipTest(
"Missing git")
2581 self.skipTest(
"Optional components are not supported on Windows")
2584 return_code, stdout, stderr =
run_ns3(
"configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON")
2585 self.assertEqual(return_code, 0)
2589 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2590 self.assertEqual(return_code, 0)
2594 Test if we can link contrib modules to src modules
2597 if shutil.which(
"git")
is None:
2598 self.skipTest(
"Missing git")
2600 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2601 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2603 if os.path.exists(destination_contrib):
2604 shutil.rmtree(destination_contrib)
2605 if os.path.exists(destination_src):
2606 shutil.rmtree(destination_src)
2610 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2611 destination_contrib,
2614 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2619 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2620 self.assertEqual(return_code, 0)
2623 return_code, stdout, stderr =
run_ns3(
"run source-example")
2624 self.assertEqual(return_code, 0)
2627 shutil.rmtree(destination_contrib)
2628 shutil.rmtree(destination_src)
2633 Tests ns3 usage in more realistic scenarios
2638 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2639 Here examples, tests and documentation are also enabled.
2646 return_code, stdout, stderr =
run_ns3(
2647 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2649 self.
config_ok(return_code, stdout, stderr)
2652 self.assertTrue(os.path.exists(ns3_lock_filename))
2658 self.assertTrue(os.path.exists(ns3_lock_filename))
2665 Try to build the project
2668 return_code, stdout, stderr =
run_ns3(
"build")
2669 self.assertEqual(return_code, 0)
2670 self.assertIn(
"Built target", stdout)
2672 self.assertTrue(os.path.exists(program))
2675 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2676 self.assertIn(cmake_build_project_command, stdout)
2680 Try to build and run test-runner
2683 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2684 self.assertEqual(return_code, 0)
2685 self.assertIn(
"Built target test-runner", stdout)
2690 Try to build and run a library
2693 return_code, stdout, stderr =
run_ns3(
"run core")
2694 self.assertEqual(return_code, 1)
2695 self.assertIn(
"Couldn't find the specified program: core", stderr)
2699 Try to build and run an unknown target
2702 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2703 self.assertEqual(return_code, 1)
2704 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2708 Try to run test-runner without building
2711 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2712 self.assertEqual(return_code, 0)
2714 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2715 self.assertEqual(return_code, 0)
2716 self.assertNotIn(
"Built target test-runner", stdout)
2721 Test ns3 fails to run a library
2724 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2725 self.assertEqual(return_code, 1)
2726 self.assertIn(
"Couldn't find the specified program: core", stderr)
2730 Test ns3 fails to run an unknown program
2733 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2734 self.assertEqual(return_code, 1)
2735 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2739 Test if scratch simulator is executed through gdb and lldb
2742 if shutil.which(
"gdb")
is None:
2743 self.skipTest(
"Missing gdb")
2745 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2746 self.assertEqual(return_code, 0)
2748 return_code, stdout, stderr =
run_ns3(
2749 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2751 self.assertEqual(return_code, 0)
2752 self.assertIn(
"scratch-simulator", stdout)
2754 self.assertIn(
"GNU gdb", stdout)
2756 self.assertIn(
"No debugging symbols found", stdout)
2760 Test if scratch simulator is executed through valgrind
2763 if shutil.which(
"valgrind")
is None:
2764 self.skipTest(
"Missing valgrind")
2766 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2767 self.assertEqual(return_code, 0)
2769 return_code, stdout, stderr =
run_ns3(
2770 "run scratch-simulator --valgrind --verbose --no-build"
2772 self.assertEqual(return_code, 0)
2773 self.assertIn(
"scratch-simulator", stderr)
2774 self.assertIn(
"Memcheck", stderr)
2778 Test the doxygen target that does trigger a full build
2781 if shutil.which(
"doxygen")
is None:
2782 self.skipTest(
"Missing doxygen")
2784 if shutil.which(
"bash")
is None:
2785 self.skipTest(
"Missing bash")
2787 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2789 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2790 for filename
in doxygen_files:
2791 file_path = os.sep.join([doc_folder, filename])
2792 if os.path.exists(file_path):
2793 os.remove(file_path)
2800 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2801 self.assertEqual(return_code, 0)
2803 self.assertIn(
"Built target doxygen", stdout)
2807 Test the doxygen target that doesn't trigger a full build
2810 if shutil.which(
"doxygen")
is None:
2811 self.skipTest(
"Missing doxygen")
2819 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2820 self.assertEqual(return_code, 0)
2822 self.assertIn(
"Built target doxygen-no-build", stdout)
2826 Test every individual target for Sphinx-based documentation
2829 if shutil.which(
"sphinx-build")
is None:
2830 self.skipTest(
"Missing sphinx")
2832 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2835 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2837 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2838 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2839 if os.path.exists(doc_build_folder):
2840 shutil.rmtree(doc_build_folder)
2841 if os.path.exists(doc_temp_folder):
2842 shutil.rmtree(doc_temp_folder)
2845 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2846 self.assertEqual(return_code, 0, target)
2848 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2851 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2852 self.assertTrue(os.path.exists(doc_build_folder))
2855 for build_type
in [
"latex",
"html",
"singlehtml"]:
2856 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2860 Test the documentation target that builds
2861 both doxygen and sphinx based documentation
2864 if shutil.which(
"doxygen")
is None:
2865 self.skipTest(
"Missing doxygen")
2866 if shutil.which(
"sphinx-build")
is None:
2867 self.skipTest(
"Missing sphinx")
2869 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2878 for target
in [
"manual",
"models",
"tutorial"]:
2879 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2880 if os.path.exists(doc_build_folder):
2881 shutil.rmtree(doc_build_folder)
2883 return_code, stdout, stderr =
run_ns3(
"docs all")
2884 self.assertEqual(return_code, 0)
2886 self.assertIn(
"Built target sphinx", stdout)
2888 self.assertIn(
"Built target doxygen", stdout)
2892 Try to set ownership of scratch-simulator from current user to root,
2893 and change execution permissions
2898 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2901 if sudo_password
is None:
2902 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2905 self.assertFalse(enable_sudo
is True)
2908 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2909 self.assertEqual(return_code, 0)
2910 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2912 scratch_simulator_path = list(
2913 filter(
lambda x: x
if "scratch-simulator" in x
else None, self.
ns3_executables)
2915 prev_fstat = os.stat(scratch_simulator_path)
2918 return_code, stdout, stderr =
run_ns3(
2919 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2921 self.assertEqual(return_code, 0)
2922 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2924 fstat = os.stat(scratch_simulator_path)
2930 likely_fuse_mount = (
2931 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2932 )
and prev_fstat.st_uid == 0
2934 if win32
or likely_fuse_mount:
2935 self.skipTest(
"Windows or likely a FUSE mount")
2938 self.assertEqual(fstat.st_uid, 0)
2940 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2944 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2945 self.assertEqual(return_code, 0)
2949 self.assertTrue(enable_sudo)
2953 if os.path.exists(executable):
2954 os.remove(executable)
2957 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2958 self.assertEqual(return_code, 0)
2961 self.assertIn(
"chown root", stdout)
2962 self.assertIn(
"chmod u+s", stdout)
2964 self.assertIn(os.path.basename(executable), stdout)
2967 fstat = os.stat(scratch_simulator_path)
2968 self.assertEqual(fstat.st_uid, 0)
2970 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2975 Check if command template is working
2980 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
2981 self.assertEqual(return_code0, 2)
2982 self.assertIn(
"argument --command-template: expected one argument", stderr0)
2984 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
2985 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
2986 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
2987 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
2988 for stderr
in [stderr1, stderr2, stderr3]:
2989 self.assertIn(
"not all arguments converted during string formatting", stderr)
2992 return_code4, stdout4, _ =
run_ns3(
2993 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
2995 return_code5, stdout5, _ =
run_ns3(
2996 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
2998 self.assertEqual((return_code4, return_code5), (0, 0))
3000 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3001 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3005 Check if all flavors of different argument passing to
3006 executable targets are working
3011 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3012 return_code1, stdout1, stderr1 =
run_ns3(
3013 'run sample-simulator --command-template="%s --help" --verbose'
3015 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3017 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3018 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3019 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3020 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3023 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3024 return_code1, stdout1, stderr1 =
run_ns3(
3025 'run sample-simulator --command-template="%s --help" --no-build'
3027 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3028 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3029 self.assertEqual(stdout0, stdout1)
3030 self.assertEqual(stdout1, stdout2)
3031 self.assertEqual(stderr0, stderr1)
3032 self.assertEqual(stderr1, stderr2)
3035 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3036 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3037 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3039 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3040 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3041 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3042 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3045 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3046 return_code, stdout, stderr =
run_ns3(cmd)
3047 self.assertEqual(return_code, 0)
3053 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3058 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3059 cmd1 =
"run sample-simulator --PrintTypeIds"
3061 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3062 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3063 self.assertEqual((return_code0, return_code1), (1, 1))
3064 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3065 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3069 Test if scratch simulator is executed through lldb
3072 if shutil.which(
"lldb")
is None:
3073 self.skipTest(
"Missing lldb")
3075 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3076 self.assertEqual(return_code, 0)
3078 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3079 self.assertEqual(return_code, 0)
3080 self.assertIn(
"scratch-simulator", stdout)
3081 self.assertIn(
"(lldb) target create", stdout)
3085 Test if CPM and Vcpkg package managers are working properly
3089 return_code, stdout, stderr =
run_ns3(
"clean")
3090 self.assertEqual(return_code, 0)
3093 if os.path.exists(
"vcpkg"):
3094 shutil.rmtree(
"vcpkg")
3097 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3099 if os.path.exists(destination_src):
3100 shutil.rmtree(destination_src)
3104 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3110 container.execute(
"apt-get update")
3111 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3116 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3117 self.skipTest(
"Armadillo is already installed")
3118 except DockerException
as e:
3122 return_code, stdout, stderr =
run_ns3(
"clean")
3123 self.assertEqual(return_code, 0)
3126 container.execute(
"apt-get install -y git")
3131 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3133 except DockerException
as e:
3138 container.execute(
"./ns3 build test-package-managers")
3139 except DockerException
as e:
3143 return_code, stdout, stderr =
run_ns3(
"clean")
3144 self.assertEqual(return_code, 0)
3146 if arch !=
"aarch64":
3148 container.execute(
"apt-get install -y zip unzip tar curl")
3151 container.execute(
"apt-get install -y pkg-config gfortran")
3155 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3156 except DockerException
as e:
3161 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3162 except DockerException
as e:
3167 container.execute(
"./ns3 build test-package-managers")
3168 except DockerException
as e:
3172 if os.path.exists(destination_src):
3173 shutil.rmtree(destination_src)
3178 ns-3 tests to control the quality of the repository over time
3183 Check if images in the docs are above a brightness threshold.
3184 This should prevent screenshots with dark UI themes.
3187 if shutil.which(
"convert")
is None:
3188 self.skipTest(
"Imagemagick was not found")
3190 from pathlib
import Path
3193 image_extensions = [
"png",
"jpg"]
3195 for extension
in image_extensions:
3196 images += list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3197 images += list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3200 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3204 brightness_threshold = 50
3205 for image
in images:
3206 brightness = subprocess.check_output(
3207 imagemagick_get_image_brightness.format(image=image).split()
3209 brightness = float(brightness.decode().strip(
"'\""))
3212 brightness_threshold,
3213 "Image darker than threshold (%d < %d): %s"
3214 % (brightness, brightness_threshold, image),
3219 Check if one of the log statements of examples/tests contains/exposes a bug.
3223 return_code, stdout, stderr =
run_ns3(
3224 'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
3226 self.assertEqual(return_code, 0)
3230 "test.py",
"", python=
True, env={
"TEST_LOGS":
"1"}
3232 self.assertEqual(return_code, 0)
3237 ns-3 complementary tests, allowed to fail, to help control
3238 the quality of the repository over time, by checking the
3239 state of URLs listed and more
3244 Test if all urls in source files are alive
3253 self.skipTest(
"Django URL validators are not available")
3260 urllib3.disable_warnings()
3263 self.skipTest(
"Requests library is not available")
3265 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3268 whitelisted_urls = {
3269 "https://gitlab.com/your-user-name/ns-3-dev",
3270 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3271 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3272 "https://www.nsnam.org/releases/ns-3-x",
3273 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3274 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3275 "https://ns-buildmaster.ee.washington.edu:8010/",
3277 "https://cmake.org/cmake/help/latest/manual/cmake-",
3278 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3280 "http://www.lysator.liu.se/~alla/dia/",
3282 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3283 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3284 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3285 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3286 "https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch",
3287 "http://www.nsnam.org/bugzilla/show_bug.cgi?id=",
3289 "http://www.research.att.com/info/kpv/",
3290 "http://www.research.att.com/~gsf/",
3291 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3292 "http://scan5.coverity.com/cgi-bin/upload.py",
3294 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3295 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3299 files_and_urls = set()
3301 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3302 for root, dirs, files
in os.walk(topdir):
3304 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3307 filepath = os.path.join(root, file)
3310 if not os.path.isfile(filepath):
3314 if file.endswith(
".svg"):
3318 with open(filepath,
"r", encoding=
"utf-8")
as f:
3319 matches = regex.findall(f.read())
3325 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3327 except UnicodeDecodeError:
3328 skipped_files.append(filepath)
3332 for url
in set(urls) - unique_urls - whitelisted_urls:
3333 unique_urls.add(url)
3334 files_and_urls.add((filepath, url))
3337 from django.core.exceptions
import ValidationError
3338 from django.core.validators
import URLValidator
3340 validate_url = URLValidator()
3344 "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"
3348 def test_file_url(args):
3349 test_filepath, test_url = args
3350 dead_link_msg =
None
3354 validate_url(test_url)
3355 except ValidationError:
3356 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3357 except Exception
as e:
3358 self.assertEqual(
False,
True, msg=e.__str__())
3360 if dead_link_msg
is not None:
3361 return dead_link_msg
3369 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3372 if response.status_code
in [200, 301]:
3373 dead_link_msg =
None
3378 if response.status_code
in [302, 308, 500, 503]:
3379 if response.reason.lower()
in [
3381 "moved temporarily",
3382 "permanent redirect",
3384 "service temporarily unavailable",
3386 dead_link_msg =
None
3390 dead_link_msg =
"%s: URL %s: returned code %d" % (
3393 response.status_code,
3395 except requests.exceptions.InvalidURL:
3396 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3397 except requests.exceptions.SSLError:
3398 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3399 except requests.exceptions.TooManyRedirects:
3400 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3401 except Exception
as e:
3403 error_msg = e.args[0].reason.__str__()
3404 except AttributeError:
3405 error_msg = e.args[0]
3406 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3412 return dead_link_msg
3415 from concurrent.futures
import ThreadPoolExecutor
3417 with ThreadPoolExecutor(max_workers=100)
as executor:
3418 dead_links = list(executor.map(test_file_url, list(files_and_urls)))
3421 dead_links = list(sorted(filter(
lambda x: x
is not None, dead_links)))
3422 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3426 Test if all tests can be executed without hitting major memory bugs
3429 return_code, stdout, stderr =
run_ns3(
3430 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3432 self.assertEqual(return_code, 0)
3434 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3435 self.assertEqual(test_return_code, 0)
3444 test_completeness = {
3446 NS3UnusedSourcesTestCase,
3450 NS3CommonSettingsTestCase,
3451 NS3ConfigureBuildProfileTestCase,
3452 NS3ConfigureTestCase,
3453 NS3BuildBaseTestCase,
3454 NS3ExpectedUseTestCase,
3457 NS3UnusedSourcesTestCase,
3459 NS3CommonSettingsTestCase,
3460 NS3ConfigureBuildProfileTestCase,
3461 NS3ConfigureTestCase,
3462 NS3BuildBaseTestCase,
3463 NS3ExpectedUseTestCase,
3464 NS3QualityControlTestCase,
3467 NS3DependenciesTestCase,
3468 NS3QualityControlThatCanFailTestCase,
3474 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3475 parser.add_argument(
3476 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3478 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3479 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3480 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3481 parser.add_argument(
"-f",
"--failfast", action=
"store_true", default=
False)
3482 args = parser.parse_args(sys.argv[1:])
3484 loader = unittest.TestLoader()
3485 suite = unittest.TestSuite()
3488 for testCase
in test_completeness[args.completeness]:
3489 suite.addTests(loader.loadTestsFromTestCase(testCase))
3494 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3496 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3497 tests_to_remove = set(tests) - set(tests_to_run)
3498 for test_to_remove
in tests_to_remove:
3499 suite._tests.remove(tests[test_to_remove])
3502 if args.resume_from_test_name:
3504 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3505 keys = list(tests.keys())
3507 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3508 suite._tests.remove(tests[keys[0]])
3512 ns3rc_script_bak = ns3rc_script +
".bak"
3513 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3514 shutil.move(ns3rc_script, ns3rc_script_bak)
3517 runner = unittest.TextTestRunner(failfast=args.failfast, verbosity=1
if args.quiet
else 2)
3521 if os.path.exists(ns3rc_script_bak):
3522 shutil.move(ns3rc_script_bak, ns3rc_script)
3525if __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_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.