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:
1260 int main (int argc, char *argv[])
1262 char *s = "hello world"; *s = 'H';
1267 return_code, stdout, stderr =
run_ns3(
"run sigsegv")
1269 self.assertEqual(return_code, 4294967295)
1270 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1272 self.assertEqual(return_code, 245)
1273 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1276 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1277 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1280 #include "ns3/core-module.h"
1282 using namespace ns3;
1283 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:
1518 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1519 LIBRARIES_TO_LINK ${libcore} %s
1522 % invalid_or_nonexistent_library
1525 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1526 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1527 self.assertEqual(return_code, 0)
1528 elif invalid_or_nonexistent_library
in [
"lib"]:
1529 self.assertEqual(return_code, 1)
1530 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1534 return_code, stdout, stderr =
run_ns3(
"build borked")
1535 if invalid_or_nonexistent_library
in [
""]:
1536 self.assertEqual(return_code, 0)
1537 elif invalid_or_nonexistent_library
in [
"lib"]:
1538 self.assertEqual(return_code, 2)
1539 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1540 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1541 self.assertEqual(return_code, 2)
1542 if "lld" in stdout + stderr:
1544 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1546 elif "mold" in stdout + stderr:
1547 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1550 "library not found for -l%s" % invalid_or_nonexistent_library, stderr
1553 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1561 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1566 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1567 LIBRARIES_TO_LINK ${libcore}
1571 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1572 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1577 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1578 LIBRARIES_TO_LINK ${libborked} %s
1581 % invalid_or_nonexistent_library
1584 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1585 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1586 self.assertEqual(return_code, 0)
1587 elif invalid_or_nonexistent_library
in [
"lib"]:
1588 self.assertEqual(return_code, 1)
1589 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1593 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1594 if invalid_or_nonexistent_library
in [
""]:
1595 self.assertEqual(return_code, 0)
1596 elif invalid_or_nonexistent_library
in [
"libf"]:
1597 self.assertEqual(return_code, 2)
1598 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1599 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1600 self.assertEqual(return_code, 1)
1601 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1605 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1609 Test if CMake can properly handle modules containing "lib",
1610 which is used internally as a prefix for module libraries
1614 os.makedirs(
"contrib/calibre", exist_ok=
True)
1615 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1618 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1620 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1625 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1626 LIBRARIES_TO_LINK ${libcore}
1631 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1634 self.assertEqual(return_code, 0)
1637 self.assertIn(
"calibre", stdout)
1641 self.assertNotIn(
"care", stdout)
1643 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1647 return_code, stdout, stderr =
run_ns3(
"build calibre")
1648 self.assertEqual(return_code, 0)
1651 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1655 Test if CMake performance tracing works and produces the
1656 cmake_performance_trace.log file
1659 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1660 if os.path.exists(cmake_performance_trace_log):
1661 os.remove(cmake_performance_trace_log)
1663 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1664 self.assertEqual(return_code, 0)
1666 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1669 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1672 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1676 Check if ENABLE_BUILD_VERSION and version.cache are working
1684 container.execute(
"apt-get update")
1685 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1688 container.execute(
"./ns3 clean")
1691 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1694 if os.path.exists(version_cache_file):
1695 os.remove(version_cache_file)
1699 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1700 except DockerException:
1702 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1705 version_cache_contents = (
1706 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1707 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1708 "VERSION_DIRTY_FLAG = '0'\n"
1709 "VERSION_MAJOR = '3'\n"
1710 "VERSION_MINOR = '0'\n"
1711 "VERSION_PATCH = '0'\n"
1712 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1713 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1714 "VERSION_TAG_DISTANCE = '0'\n"
1715 "VERSION_BUILD_PROFILE = 'debug'\n"
1717 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1718 version.write(version_cache_contents)
1721 container.execute(
"./ns3 clean")
1722 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1723 container.execute(
"./ns3 build core")
1724 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1727 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1728 self.assertEqual(version.read(), version_cache_contents)
1733 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1735 container.execute(
"apt-get install -y git")
1736 container.execute(
"./ns3 clean")
1737 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1738 container.execute(
"./ns3 build core")
1739 except DockerException:
1741 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1742 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1745 container.execute(
"./ns3 clean")
1746 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1747 container.execute(
"./ns3 build core")
1748 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1749 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1750 self.assertNotEqual(version.read(), version_cache_contents)
1753 if os.path.exists(version_cache_file):
1754 os.remove(version_cache_file)
1758 Test filtering in examples and tests from specific modules
1762 return_code, stdout, stderr =
run_ns3(
1763 'configure -G "{generator}" --enable-examples --enable-tests'
1765 self.
config_ok(return_code, stdout, stderr)
1770 return_code, stdout, stderr =
run_ns3(
1771 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1773 self.
config_ok(return_code, stdout, stderr)
1779 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1781 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1784 return_code, stdout, stderr =
run_ns3(
1785 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1787 self.
config_ok(return_code, stdout, stderr)
1795 return_code, stdout, stderr =
run_ns3(
1796 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1798 self.
config_ok(return_code, stdout, stderr)
1806 Check if fast linkers LLD and Mold are correctly found and configured
1813 container.execute(
"apt-get update")
1814 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1817 container.execute(
"./ns3 configure -G Ninja")
1820 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1822 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1824 self.assertIn(
"-fuse-ld=lld", f.read())
1828 container.execute(
"./ns3 build core")
1829 except DockerException:
1830 self.assertTrue(
False,
"Build with lld failed")
1833 if not os.path.exists(f
"./mold-1.4.2-{arch}-linux.tar.gz"):
1835 f
"wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch}-linux.tar.gz"
1838 f
"tar xzfC mold-1.4.2-{arch}-linux.tar.gz /usr/local --strip-components=1"
1843 container.execute(
"./ns3 configure -G Ninja")
1846 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1848 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1850 self.assertIn(
"-fuse-ld=mold", f.read())
1854 container.execute(
"./ns3 build core")
1855 except DockerException:
1856 self.assertTrue(
False,
"Build with mold failed")
1859 os.remove(f
"./mold-1.4.2-{arch}-linux.tar.gz")
1862 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1865 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1867 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1869 self.assertNotIn(
"-fuse-ld=mold", f.read())
1873 Check if NS3_CLANG_TIMETRACE feature is working
1874 Clang's -ftime-trace plus ClangAnalyzer report
1880 container.execute(
"apt-get update")
1881 container.execute(
"apt-get install -y python3 ninja-build cmake clang-18")
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)
1891 container.execute(
"apt-get install -y git")
1896 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1898 except DockerException
as e:
1899 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1902 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1903 if os.path.exists(time_trace_report_path):
1904 os.remove(time_trace_report_path)
1908 container.execute(
"./ns3 build timeTraceReport")
1909 except DockerException
as e:
1910 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1913 self.assertTrue(os.path.exists(time_trace_report_path))
1917 container.execute(
"apt-get install -y g++")
1918 container.execute(
"apt-get remove -y clang-18")
1922 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1925 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1927 except DockerException
as e:
1928 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1932 Check if NS3_NINJA_TRACE feature is working
1933 Ninja's .ninja_log conversion to about://tracing
1934 json format conversion with Ninjatracing
1940 container.execute(
"apt-get update")
1941 container.execute(
"apt-get remove -y g++")
1942 container.execute(
"apt-get install -y python3 cmake g++-11 clang-18")
1947 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1949 except DockerException
as e:
1950 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1955 container.execute(
"apt-get install -y ninja-build")
1959 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1961 except DockerException
as e:
1962 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1964 container.execute(
"apt-get install -y git")
1968 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1970 except DockerException
as e:
1971 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1974 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1975 if os.path.exists(ninja_trace_path):
1976 os.remove(ninja_trace_path)
1979 container.execute(
"./ns3 build core")
1983 container.execute(
"./ns3 build ninjaTrace")
1984 except DockerException
as e:
1985 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1988 self.assertTrue(os.path.exists(ninja_trace_path))
1989 trace_size = os.stat(ninja_trace_path).st_size
1990 os.remove(ninja_trace_path)
1997 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1999 except DockerException
as e:
2000 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
2003 container.execute(
"./ns3 build core")
2007 container.execute(
"./ns3 build ninjaTrace")
2008 except DockerException
as e:
2009 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
2011 self.assertTrue(os.path.exists(ninja_trace_path))
2012 timetrace_size = os.stat(ninja_trace_path).st_size
2013 os.remove(ninja_trace_path)
2016 self.assertGreater(timetrace_size, trace_size)
2020 Check if precompiled headers are being enabled correctly.
2030 container.execute(
"apt-get update")
2031 container.execute(
"apt-get install -y python3 cmake ccache g++")
2033 container.execute(
"./ns3 configure")
2034 except DockerException
as e:
2035 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2039 Check for regressions in test object build.
2042 return_code, stdout, stderr =
run_ns3(
"configure")
2043 self.assertEqual(return_code, 0)
2045 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2046 self.assertFalse(os.path.exists(test_module_cache))
2048 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2049 self.assertEqual(return_code, 0)
2050 self.assertTrue(os.path.exists(test_module_cache))
2054 Check for regressions in a bare ns-3 configuration.
2061 container.execute(
"apt-get update")
2062 container.execute(
"apt-get install -y python3 cmake g++")
2066 stdout = container.execute(
"./ns3 configure -d release")
2067 except DockerException
as e:
2069 self.
config_ok(return_code, stdout, stdout)
2076 Tests ns3 regarding building the project
2081 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2090 Try building the core library
2093 return_code, stdout, stderr =
run_ns3(
"build core")
2094 self.assertEqual(return_code, 0)
2095 self.assertIn(
"Built target core", stdout)
2099 Try building core-test library without tests enabled
2103 return_code, stdout, stderr =
run_ns3(
"build core-test")
2104 self.assertEqual(return_code, 1)
2105 self.assertIn(
"Target to build does not exist: core-test", stdout)
2109 Try building the project:
2112 return_code, stdout, stderr =
run_ns3(
"build")
2113 self.assertEqual(return_code, 0)
2114 self.assertIn(
"Built target", stdout)
2116 self.assertTrue(os.path.exists(program), program)
2117 self.assertIn(cmake_build_project_command, stdout)
2121 Try hiding task lines
2124 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2125 self.assertEqual(return_code, 0)
2126 self.assertIn(cmake_build_project_command, stdout)
2130 Try removing an essential file to break the build
2134 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2135 attribute_cc_bak_path = attribute_cc_path +
".bak"
2136 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2139 return_code, stdout, stderr =
run_ns3(
"build")
2140 self.assertNotEqual(return_code, 0)
2143 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2146 return_code, stdout, stderr =
run_ns3(
"build")
2147 self.assertEqual(return_code, 0)
2151 Test if changing the version file affects the library names
2157 version_file = os.sep.join([ns3_path,
"VERSION"])
2158 with open(version_file,
"w", encoding=
"utf-8")
as f:
2162 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2163 self.
config_ok(return_code, stdout, stderr)
2166 return_code, stdout, stderr =
run_ns3(
"build")
2167 self.assertEqual(return_code, 0)
2168 self.assertIn(
"Built target", stdout)
2174 for program
in new_programs:
2175 self.assertTrue(os.path.exists(program))
2182 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2183 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2184 for library
in new_libraries:
2185 self.assertNotIn(
"libns3-dev", library)
2186 self.assertIn(
"libns3-00", library)
2187 self.assertTrue(os.path.exists(library))
2190 with open(version_file,
"w", encoding=
"utf-8")
as f:
2195 Try setting a different output directory and if everything is
2196 in the right place and still working correctly
2201 return_code, stdout, stderr =
run_ns3(
"build")
2202 self.assertEqual(return_code, 0)
2217 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2218 relative_path = os.sep.join([
"build",
"release"])
2219 for different_out_dir
in [absolute_path, relative_path]:
2220 return_code, stdout, stderr =
run_ns3(
2221 'configure -G "{generator}" --out=%s' % different_out_dir
2223 self.
config_ok(return_code, stdout, stderr)
2225 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2234 for program
in new_programs:
2235 self.assertTrue(os.path.exists(program))
2239 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2240 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2241 for library
in new_libraries:
2242 self.assertTrue(os.path.exists(library))
2245 shutil.rmtree(absolute_path)
2248 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2249 self.
config_ok(return_code, stdout, stderr)
2251 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2260 for program
in new_programs:
2261 self.assertTrue(os.path.exists(program))
2266 for library
in libraries:
2267 self.assertTrue(os.path.exists(library))
2271 Tries setting a ns3 version, then installing it.
2272 After that, tries searching for ns-3 with CMake's find_package(ns3).
2273 Finally, tries using core library in a 3rd-party project
2278 for library
in libraries:
2282 version_file = os.sep.join([ns3_path,
"VERSION"])
2283 with open(version_file,
"w", encoding=
"utf-8")
as f:
2287 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2288 return_code, stdout, stderr =
run_ns3(
2289 'configure -G "{generator}" --prefix=%s' % install_prefix
2291 self.
config_ok(return_code, stdout, stderr)
2302 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2303 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2307 installed_libraries_list =
";".join(installed_libraries)
2308 for library
in libraries:
2309 library_name = os.path.basename(library)
2310 self.assertIn(library_name, installed_libraries_list)
2314 missing_headers = list(
2315 set([os.path.basename(x)
for x
in headers])
2316 - (set([os.path.basename(x)
for x
in installed_headers]))
2318 self.assertEqual(len(missing_headers), 0)
2321 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2322 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2325 #include <ns3/core-module.h>
2326 using namespace ns3;
2329 Simulator::Stop (Seconds (1.0));
2331 Simulator::Destroy ();
2340 for version
in [
"",
"3.01",
"3.00"]:
2341 ns3_import_methods = []
2344 cmake_find_package_import =
"""
2345 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2346 find_package(ns3 {version} COMPONENTS core)
2347 target_link_libraries(test PRIVATE ns3::core)
2349 lib=(
"lib64" if lib64
else "lib"), version=version
2351 ns3_import_methods.append(cmake_find_package_import)
2354 pkgconfig_import =
"""
2355 list(APPEND CMAKE_PREFIX_PATH ./)
2356 include(FindPkgConfig)
2357 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2358 target_link_libraries(test PUBLIC PkgConfig::ns3)
2360 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2362 if shutil.which(
"pkg-config"):
2363 ns3_import_methods.append(pkgconfig_import)
2366 for import_method
in ns3_import_methods:
2367 test_cmake_project = (
2369 cmake_minimum_required(VERSION 3.20..3.20)
2370 project(ns3_consumer CXX)
2371 set(CMAKE_CXX_STANDARD 23)
2372 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2373 add_executable(test main.cpp)
2378 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2379 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2380 f.write(test_cmake_project)
2383 cmake = shutil.which(
"cmake")
2386 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2387 generator=platform_makefiles
2392 if version ==
"3.00":
2393 self.assertEqual(return_code, 1)
2394 if import_method == cmake_find_package_import:
2396 'Could not find a configuration file for package "ns3" that is compatible',
2397 stderr.replace(
"\n",
""),
2399 elif import_method == pkgconfig_import:
2400 self.assertIn(
"not found", stderr.replace(
"\n",
""))
2402 raise Exception(
"Unknown import type")
2404 self.assertEqual(return_code, 0)
2405 self.assertIn(
"Build files", stdout)
2408 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2410 if version ==
"3.00":
2411 self.assertEqual(return_code, 2, msg=stdout + stderr)
2412 self.assertGreater(len(stderr), 0)
2414 self.assertEqual(return_code, 0)
2415 self.assertIn(
"Built target", stdout)
2419 test_program = os.path.join(install_prefix,
"test.exe")
2420 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2422 "PATH": env_sep.join(
2423 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2427 test_program =
"./test"
2430 test_program,
"", cwd=install_prefix, env=env
2432 self.assertEqual(return_code, 0)
2435 return_code, stdout, stderr =
run_ns3(
"uninstall")
2436 self.assertIn(
"Built target uninstall", stdout)
2439 os.remove(version_file)
2440 with open(version_file,
"w", encoding=
"utf-8")
as f:
2445 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2450 "scratch/scratch-simulator":
"scratch-simulator",
2451 "scratch/scratch-simulator.cc":
"scratch-simulator",
2452 "scratch-simulator":
"scratch-simulator",
2453 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2454 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2455 "scratch-subdir":
"subdir_scratch-subdir",
2457 for target_to_run, target_cmake
in targets.items():
2459 build_line =
"target scratch_%s" % target_cmake
2460 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2461 self.assertEqual(return_code, 0)
2462 self.assertIn(build_line, stdout)
2465 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2466 self.assertEqual(return_code, 0)
2467 self.assertIn(build_line, stdout)
2468 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2469 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2473 Test if ns3 can alert correctly in case a shortcut collision happens
2478 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2479 self.assertEqual(return_code, 0)
2482 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2485 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2486 self.assertEqual(return_code, 0)
2489 return_code, stdout, stderr =
run_ns3(
"build second")
2490 self.assertEqual(return_code, 1)
2492 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2493 stdout.replace(os.sep,
"/"),
2497 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2498 self.assertEqual(return_code, 0)
2502 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2503 self.assertEqual(return_code, 0)
2507 return_code, stdout, stderr =
run_ns3(
"run second")
2508 self.assertEqual(return_code, 1)
2510 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2511 stdout.replace(os.sep,
"/"),
2515 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2516 self.assertEqual(return_code, 0)
2519 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2520 self.assertEqual(return_code, 0)
2523 os.remove(
"./scratch/second.cc")
2527 Test if we can build a static ns-3 library and link it to static programs
2530 if (
not win32)
and (arch ==
"aarch64"):
2531 if platform.libc_ver()[0] ==
"glibc":
2532 from packaging.version
import Version
2534 if Version(platform.libc_ver()[1]) < Version(
"2.37"):
2536 "Static linking on ARM64 requires glibc 2.37 where fPIC was enabled (fpic is limited in number of GOT entries)"
2540 return_code, stdout, stderr =
run_ns3(
2541 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2547 self.assertEqual(return_code, 1)
2548 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2551 self.assertEqual(return_code, 0)
2554 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2555 self.assertEqual(return_code, 0)
2556 self.assertIn(
"Built target", stdout)
2562 Test if we can use python bindings
2567 except ModuleNotFoundError:
2568 self.skipTest(
"Cppyy was not found")
2571 return_code, stdout, stderr =
run_ns3(
2572 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2576 self.assertEqual(return_code, 0)
2579 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2580 self.assertEqual(return_code, 0)
2583 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2584 self.assertEqual(return_code, 0)
2588 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2590 self.assertEqual(return_code, 0)
2594 Test if we had regressions with brite, click and openflow modules
2595 that depend on homonymous libraries
2598 if shutil.which(
"git")
is None:
2599 self.skipTest(
"Missing git")
2602 self.skipTest(
"Optional components are not supported on Windows")
2605 return_code, stdout, stderr =
run_ns3(
"configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON")
2606 self.assertEqual(return_code, 0)
2610 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2611 self.assertEqual(return_code, 0)
2615 Test if we can link contrib modules to src modules
2618 if shutil.which(
"git")
is None:
2619 self.skipTest(
"Missing git")
2621 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2622 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2624 if os.path.exists(destination_contrib):
2625 shutil.rmtree(destination_contrib)
2626 if os.path.exists(destination_src):
2627 shutil.rmtree(destination_src)
2631 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2632 destination_contrib,
2635 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2640 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2641 self.assertEqual(return_code, 0)
2644 return_code, stdout, stderr =
run_ns3(
"run source-example")
2645 self.assertEqual(return_code, 0)
2648 shutil.rmtree(destination_contrib)
2649 shutil.rmtree(destination_src)
2654 Tests ns3 usage in more realistic scenarios
2659 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2660 Here examples, tests and documentation are also enabled.
2667 return_code, stdout, stderr =
run_ns3(
2668 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2670 self.
config_ok(return_code, stdout, stderr)
2673 self.assertTrue(os.path.exists(ns3_lock_filename))
2679 self.assertTrue(os.path.exists(ns3_lock_filename))
2686 Try to build the project
2689 return_code, stdout, stderr =
run_ns3(
"build")
2690 self.assertEqual(return_code, 0)
2691 self.assertIn(
"Built target", stdout)
2693 self.assertTrue(os.path.exists(program))
2696 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2697 self.assertIn(cmake_build_project_command, stdout)
2701 Try to build and run test-runner
2704 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2705 self.assertEqual(return_code, 0)
2706 self.assertIn(
"Built target test-runner", stdout)
2711 Try to build and run a library
2714 return_code, stdout, stderr =
run_ns3(
"run core")
2715 self.assertEqual(return_code, 1)
2716 self.assertIn(
"Couldn't find the specified program: core", stderr)
2720 Try to build and run an unknown target
2723 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2724 self.assertEqual(return_code, 1)
2725 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2729 Try to run test-runner without building
2732 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2733 self.assertEqual(return_code, 0)
2735 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2736 self.assertEqual(return_code, 0)
2737 self.assertNotIn(
"Built target test-runner", stdout)
2742 Test ns3 fails to run a library
2745 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2746 self.assertEqual(return_code, 1)
2747 self.assertIn(
"Couldn't find the specified program: core", stderr)
2751 Test ns3 fails to run an unknown program
2754 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2755 self.assertEqual(return_code, 1)
2756 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2760 Test if scratch simulator is executed through gdb and lldb
2763 if shutil.which(
"gdb")
is None:
2764 self.skipTest(
"Missing gdb")
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 --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2772 self.assertEqual(return_code, 0)
2773 self.assertIn(
"scratch-simulator", stdout)
2775 self.assertIn(
"GNU gdb", stdout)
2777 self.assertIn(
"No debugging symbols found", stdout)
2781 Test if scratch simulator is executed through valgrind
2784 if shutil.which(
"valgrind")
is None:
2785 self.skipTest(
"Missing valgrind")
2787 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2788 self.assertEqual(return_code, 0)
2790 return_code, stdout, stderr =
run_ns3(
2791 "run scratch-simulator --valgrind --verbose --no-build"
2793 self.assertEqual(return_code, 0)
2794 self.assertIn(
"scratch-simulator", stderr)
2795 self.assertIn(
"Memcheck", stderr)
2799 Test the doxygen target that does trigger a full build
2802 if shutil.which(
"doxygen")
is None:
2803 self.skipTest(
"Missing doxygen")
2805 if shutil.which(
"bash")
is None:
2806 self.skipTest(
"Missing bash")
2808 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2810 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2811 for filename
in doxygen_files:
2812 file_path = os.sep.join([doc_folder, filename])
2813 if os.path.exists(file_path):
2814 os.remove(file_path)
2821 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2822 self.assertEqual(return_code, 0)
2824 self.assertIn(
"Built target doxygen", stdout)
2828 Test the doxygen target that doesn't trigger a full build
2831 if shutil.which(
"doxygen")
is None:
2832 self.skipTest(
"Missing doxygen")
2840 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2841 self.assertEqual(return_code, 0)
2843 self.assertIn(
"Built target doxygen-no-build", stdout)
2847 Test every individual target for Sphinx-based documentation
2850 if shutil.which(
"sphinx-build")
is None:
2851 self.skipTest(
"Missing sphinx")
2853 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2856 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2858 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2859 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2860 if os.path.exists(doc_build_folder):
2861 shutil.rmtree(doc_build_folder)
2862 if os.path.exists(doc_temp_folder):
2863 shutil.rmtree(doc_temp_folder)
2866 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2867 self.assertEqual(return_code, 0, target)
2869 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2872 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2873 self.assertTrue(os.path.exists(doc_build_folder))
2876 for build_type
in [
"latex",
"html",
"singlehtml"]:
2877 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2881 Test the documentation target that builds
2882 both doxygen and sphinx based documentation
2885 if shutil.which(
"doxygen")
is None:
2886 self.skipTest(
"Missing doxygen")
2887 if shutil.which(
"sphinx-build")
is None:
2888 self.skipTest(
"Missing sphinx")
2890 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2899 for target
in [
"manual",
"models",
"tutorial"]:
2900 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2901 if os.path.exists(doc_build_folder):
2902 shutil.rmtree(doc_build_folder)
2904 return_code, stdout, stderr =
run_ns3(
"docs all")
2905 self.assertEqual(return_code, 0)
2907 self.assertIn(
"Built target sphinx", stdout)
2909 self.assertIn(
"Built target doxygen", stdout)
2913 Try to set ownership of scratch-simulator from current user to root,
2914 and change execution permissions
2919 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2922 if sudo_password
is None:
2923 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2926 self.assertFalse(enable_sudo
is True)
2929 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2930 self.assertEqual(return_code, 0)
2931 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2933 scratch_simulator_path = list(
2934 filter(
lambda x: x
if "scratch-simulator" in x
else None, self.
ns3_executables)
2936 prev_fstat = os.stat(scratch_simulator_path)
2939 return_code, stdout, stderr =
run_ns3(
2940 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2942 self.assertEqual(return_code, 0)
2943 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2945 fstat = os.stat(scratch_simulator_path)
2951 likely_fuse_mount = (
2952 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2953 )
and prev_fstat.st_uid == 0
2955 if win32
or likely_fuse_mount:
2956 self.skipTest(
"Windows or likely a FUSE mount")
2959 self.assertEqual(fstat.st_uid, 0)
2961 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2965 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2966 self.assertEqual(return_code, 0)
2970 self.assertTrue(enable_sudo)
2974 if os.path.exists(executable):
2975 os.remove(executable)
2978 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2979 self.assertEqual(return_code, 0)
2982 self.assertIn(
"chown root", stdout)
2983 self.assertIn(
"chmod u+s", stdout)
2985 self.assertIn(os.path.basename(executable), stdout)
2988 fstat = os.stat(scratch_simulator_path)
2989 self.assertEqual(fstat.st_uid, 0)
2991 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2996 Check if command template is working
3001 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
3002 self.assertEqual(return_code0, 2)
3003 self.assertIn(
"argument --command-template: expected one argument", stderr0)
3005 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
3006 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
3007 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
3008 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
3009 for stderr
in [stderr1, stderr2, stderr3]:
3010 self.assertIn(
"not all arguments converted during string formatting", stderr)
3013 return_code4, stdout4, _ =
run_ns3(
3014 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
3016 return_code5, stdout5, _ =
run_ns3(
3017 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
3019 self.assertEqual((return_code4, return_code5), (0, 0))
3021 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3022 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3026 Check if all flavors of different argument passing to
3027 executable targets are working
3032 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3033 return_code1, stdout1, stderr1 =
run_ns3(
3034 'run sample-simulator --command-template="%s --help" --verbose'
3036 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3038 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3039 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3040 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3041 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3044 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3045 return_code1, stdout1, stderr1 =
run_ns3(
3046 'run sample-simulator --command-template="%s --help" --no-build'
3048 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3049 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3050 self.assertEqual(stdout0, stdout1)
3051 self.assertEqual(stdout1, stdout2)
3052 self.assertEqual(stderr0, stderr1)
3053 self.assertEqual(stderr1, stderr2)
3056 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3057 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3058 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3060 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3061 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3062 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3063 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3066 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3067 return_code, stdout, stderr =
run_ns3(cmd)
3068 self.assertEqual(return_code, 0)
3074 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3079 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3080 cmd1 =
"run sample-simulator --PrintTypeIds"
3082 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3083 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3084 self.assertEqual((return_code0, return_code1), (1, 1))
3085 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3086 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3090 Test if scratch simulator is executed through lldb
3093 if shutil.which(
"lldb")
is None:
3094 self.skipTest(
"Missing lldb")
3096 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3097 self.assertEqual(return_code, 0)
3099 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3100 self.assertEqual(return_code, 0)
3101 self.assertIn(
"scratch-simulator", stdout)
3102 self.assertIn(
"(lldb) target create", stdout)
3106 Test if CPM and Vcpkg package managers are working properly
3110 return_code, stdout, stderr =
run_ns3(
"clean")
3111 self.assertEqual(return_code, 0)
3114 if os.path.exists(
"vcpkg"):
3115 shutil.rmtree(
"vcpkg")
3118 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3120 if os.path.exists(destination_src):
3121 shutil.rmtree(destination_src)
3125 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3131 container.execute(
"apt-get update")
3132 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3137 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3138 self.skipTest(
"Armadillo is already installed")
3139 except DockerException
as e:
3143 return_code, stdout, stderr =
run_ns3(
"clean")
3144 self.assertEqual(return_code, 0)
3147 container.execute(
"apt-get install -y git")
3152 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3154 except DockerException
as e:
3159 container.execute(
"./ns3 build test-package-managers")
3160 except DockerException
as e:
3164 return_code, stdout, stderr =
run_ns3(
"clean")
3165 self.assertEqual(return_code, 0)
3167 if arch !=
"aarch64":
3169 container.execute(
"apt-get install -y zip unzip tar curl")
3172 container.execute(
"apt-get install -y pkg-config gfortran")
3176 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3177 except DockerException
as e:
3182 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3183 except DockerException
as e:
3188 container.execute(
"./ns3 build test-package-managers")
3189 except DockerException
as e:
3193 if os.path.exists(destination_src):
3194 shutil.rmtree(destination_src)
3199 ns-3 tests to control the quality of the repository over time
3204 Check if images in the docs are above a brightness threshold.
3205 This should prevent screenshots with dark UI themes.
3208 if shutil.which(
"convert")
is None:
3209 self.skipTest(
"Imagemagick was not found")
3211 from pathlib
import Path
3214 image_extensions = [
"png",
"jpg"]
3216 for extension
in image_extensions:
3217 images += list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3218 images += list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3221 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3225 brightness_threshold = 50
3226 for image
in images:
3227 brightness = subprocess.check_output(
3228 imagemagick_get_image_brightness.format(image=image).split()
3230 brightness = float(brightness.decode().strip(
"'\""))
3233 brightness_threshold,
3234 "Image darker than threshold (%d < %d): %s"
3235 % (brightness, brightness_threshold, image),
3240 Check if one of the log statements of examples/tests contains/exposes a bug.
3244 return_code, stdout, stderr =
run_ns3(
3245 'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
3247 self.assertEqual(return_code, 0)
3251 "test.py",
"", python=
True, env={
"TEST_LOGS":
"1"}
3253 self.assertEqual(return_code, 0)
3258 ns-3 complementary tests, allowed to fail, to help control
3259 the quality of the repository over time, by checking the
3260 state of URLs listed and more
3265 Test if all urls in source files are alive
3274 self.skipTest(
"Django URL validators are not available")
3281 urllib3.disable_warnings()
3284 self.skipTest(
"Requests library is not available")
3286 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3289 whitelisted_urls = {
3290 "https://gitlab.com/your-user-name/ns-3-dev",
3291 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3292 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3293 "https://www.nsnam.org/releases/ns-3-x",
3294 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3295 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3296 "https://ns-buildmaster.ee.washington.edu:8010/",
3298 "https://cmake.org/cmake/help/latest/manual/cmake-",
3299 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3301 "http://www.lysator.liu.se/~alla/dia/",
3303 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3304 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3305 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3306 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3307 "https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch",
3308 "http://www.nsnam.org/bugzilla/show_bug.cgi?id=",
3310 "http://www.research.att.com/info/kpv/",
3311 "http://www.research.att.com/~gsf/",
3312 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3313 "http://scan5.coverity.com/cgi-bin/upload.py",
3315 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3316 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3320 files_and_urls = set()
3322 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3323 for root, dirs, files
in os.walk(topdir):
3325 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3328 filepath = os.path.join(root, file)
3331 if not os.path.isfile(filepath):
3335 if file.endswith(
".svg"):
3339 with open(filepath,
"r", encoding=
"utf-8")
as f:
3340 matches = regex.findall(f.read())
3346 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3348 except UnicodeDecodeError:
3349 skipped_files.append(filepath)
3353 for url
in set(urls) - unique_urls - whitelisted_urls:
3354 unique_urls.add(url)
3355 files_and_urls.add((filepath, url))
3358 from django.core.exceptions
import ValidationError
3359 from django.core.validators
import URLValidator
3361 validate_url = URLValidator()
3365 "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"
3369 def test_file_url(args):
3370 test_filepath, test_url = args
3371 dead_link_msg =
None
3375 validate_url(test_url)
3376 except ValidationError:
3377 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3378 except Exception
as e:
3379 self.assertEqual(
False,
True, msg=e.__str__())
3381 if dead_link_msg
is not None:
3382 return dead_link_msg
3390 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3393 if response.status_code
in [200, 301]:
3394 dead_link_msg =
None
3399 if response.status_code
in [302, 308, 500, 503]:
3400 if response.reason.lower()
in [
3402 "moved temporarily",
3403 "permanent redirect",
3405 "service temporarily unavailable",
3407 dead_link_msg =
None
3411 dead_link_msg =
"%s: URL %s: returned code %d" % (
3414 response.status_code,
3416 except requests.exceptions.InvalidURL:
3417 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3418 except requests.exceptions.SSLError:
3419 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3420 except requests.exceptions.TooManyRedirects:
3421 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3422 except Exception
as e:
3424 error_msg = e.args[0].reason.__str__()
3425 except AttributeError:
3426 error_msg = e.args[0]
3427 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3433 return dead_link_msg
3436 from concurrent.futures
import ThreadPoolExecutor
3438 with ThreadPoolExecutor(max_workers=100)
as executor:
3439 dead_links = list(executor.map(test_file_url, list(files_and_urls)))
3442 dead_links = list(sorted(filter(
lambda x: x
is not None, dead_links)))
3443 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3447 Test if all tests can be executed without hitting major memory bugs
3450 return_code, stdout, stderr =
run_ns3(
3451 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3453 self.assertEqual(return_code, 0)
3455 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3456 self.assertEqual(test_return_code, 0)
3465 test_completeness = {
3467 NS3UnusedSourcesTestCase,
3471 NS3CommonSettingsTestCase,
3472 NS3ConfigureBuildProfileTestCase,
3473 NS3ConfigureTestCase,
3474 NS3BuildBaseTestCase,
3475 NS3ExpectedUseTestCase,
3478 NS3UnusedSourcesTestCase,
3480 NS3CommonSettingsTestCase,
3481 NS3ConfigureBuildProfileTestCase,
3482 NS3ConfigureTestCase,
3483 NS3BuildBaseTestCase,
3484 NS3ExpectedUseTestCase,
3485 NS3QualityControlTestCase,
3488 NS3DependenciesTestCase,
3489 NS3QualityControlThatCanFailTestCase,
3495 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3496 parser.add_argument(
3497 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3499 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3500 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3501 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3502 parser.add_argument(
"-f",
"--failfast", action=
"store_true", default=
False)
3503 args = parser.parse_args(sys.argv[1:])
3505 loader = unittest.TestLoader()
3506 suite = unittest.TestSuite()
3509 for testCase
in test_completeness[args.completeness]:
3510 suite.addTests(loader.loadTestsFromTestCase(testCase))
3515 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3517 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3518 tests_to_remove = set(tests) - set(tests_to_run)
3519 for test_to_remove
in tests_to_remove:
3520 suite._tests.remove(tests[test_to_remove])
3523 if args.resume_from_test_name:
3525 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3526 keys = list(tests.keys())
3528 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3529 suite._tests.remove(tests[keys[0]])
3533 ns3rc_script_bak = ns3rc_script +
".bak"
3534 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3535 shutil.move(ns3rc_script, ns3rc_script_bak)
3538 runner = unittest.TextTestRunner(failfast=args.failfast, verbosity=1
if args.quiet
else 2)
3542 if os.path.exists(ns3rc_script_bak):
3543 shutil.move(ns3rc_script_bak, ns3rc_script)
3546if __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.