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)
60 possible_leftovers = [
"contrib/borked",
"contrib/calibre"]
61 for leftover
in possible_leftovers:
62 if os.path.exists(leftover):
63 shutil.rmtree(leftover, ignore_errors=
True)
65 args = args.format(generator=generator)
70 return run_program(ns3_script, args, python=
True, env=env)
74def run_program(program, args, python=False, cwd=ns3_path, env=None):
76 Runs a program with the given arguments and returns a tuple containing (error code, stdout and stderr)
77 @param program: program to execute (or python script)
78 @param args: string containing arguments that will get split before calling the program
79 @param python: flag indicating whether the program is a python script
80 @param cwd: the working directory used that will be the root folder for the execution
81 @param env: environment variables dictionary
82 @return tuple containing (error code, stdout and stderr)
85 raise Exception(
"args should be a string")
89 arguments = [sys.executable, program]
94 arguments.extend(re.findall(
r'(?:".*?"|\S)+', args))
96 for i
in range(len(arguments)):
97 arguments[i] = arguments[i].replace(
'"',
"")
100 current_env = os.environ.copy()
104 current_env.update(env)
107 ret = subprocess.run(
109 stdin=subprocess.DEVNULL,
110 stdout=subprocess.PIPE,
111 stderr=subprocess.PIPE,
118 ret.stdout.decode(sys.stdout.encoding),
119 ret.stderr.decode(sys.stderr.encoding),
125 Extracts the programs list from .lock-ns3
126 @return list of programs.
129 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
130 exec(f.read(), globals(), values)
132 programs_list = values[
"ns3_runnable_programs"]
136 programs_list = list(map(
lambda x: x + ext, programs_list))
142 Gets a list of built libraries
143 @param lib_outdir: path containing libraries
144 @return list of built libraries.
146 libraries = glob.glob(lib_outdir +
"/*", recursive=
True)
147 return list(filter(
lambda x:
"scratch-nested-subdir-lib" not in x, libraries))
152 Gets a list of header files
153 @param outdir: path containing headers
154 @return list of headers.
156 return glob.glob(outdir +
"/**/*.h", recursive=
True)
161 Read interesting entries from the .lock-ns3 file
162 @param entry: entry to read from .lock-ns3
163 @return value of the requested entry.
166 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
167 exec(f.read(), globals(), values)
168 return values.get(entry,
None)
173 Check if tests are enabled in the .lock-ns3
181 Check if tests are enabled in the .lock-ns3
182 @return list of enabled modules (prefixed with 'ns3-').
189 Python-on-whales wrapper for Docker-based ns-3 tests
192 def __init__(self, currentTestCase: unittest.TestCase, containerName: str =
"ubuntu:latest"):
194 Create and start container with containerName in the current ns-3 directory
195 @param self: the current DockerContainerManager instance
196 @param currentTestCase: the test case instance creating the DockerContainerManager
197 @param containerName: name of the container image to be used
199 global DockerException
201 from python_on_whales
import docker
202 from python_on_whales.exceptions
import DockerException
203 except ModuleNotFoundError:
205 DockerException =
None
206 currentTestCase.skipTest(
"python-on-whales was not found")
209 with open(os.path.expanduser(
"~/.bashrc"),
"r", encoding=
"utf-8")
as f:
210 docker_settings = re.findall(
"(DOCKER_.*=.*)", f.read())
212 for setting
in docker_settings:
213 key, value = setting.split(
"=")
214 os.environ[key] = value
215 del setting, key, value
220 except DockerException
as e:
221 currentTestCase.skipTest(f
"python-on-whales returned:{e.__str__()}")
230 volumes=[(ns3_path,
"/ns-3-dev")],
234 def split_exec(docker_container, cmd):
235 return docker_container._execute(cmd.split(), workdir=
"/ns-3-dev")
242 Return the managed container when entiring the block "with DockerContainerManager() as container"
243 @param self: the current DockerContainerManager instance
244 @return container managed by DockerContainerManager.
250 Clean up the managed container at the end of the block "with DockerContainerManager() as container"
251 @param self: the current DockerContainerManager instance
252 @param exc_type: unused parameter
253 @param exc_val: unused parameter
254 @param exc_tb: unused parameter
263 ns-3 tests related to checking if source files were left behind, not being used by CMake
267 directory_and_files = {}
271 Scan all C++ source files and add them to a list based on their path
274 for root, dirs, files
in os.walk(ns3_path):
275 if "gitlab-ci-local" in root:
278 if name.endswith(
".cc"):
279 path = os.path.join(root, name)
280 directory = os.path.dirname(path)
287 Test if all example source files are being used in their respective CMakeLists.txt
290 unused_sources = set()
293 if os.sep +
"examples" not in example_directory:
297 if not os.path.exists(os.path.join(example_directory,
"CMakeLists.txt")):
302 os.path.join(example_directory,
"CMakeLists.txt"),
"r", encoding=
"utf-8"
304 cmake_contents = f.read()
309 if os.path.basename(file).replace(
".cc",
"")
not in cmake_contents:
310 unused_sources.add(file)
312 self.assertListEqual([], list(unused_sources))
316 Test if all module source files are being used in their respective CMakeLists.txt
319 unused_sources = set()
322 is_not_module =
not (
"src" in directory
or "contrib" in directory)
323 is_example = os.sep +
"examples" in directory
324 is_bindings = os.sep +
"bindings" in directory
326 if is_not_module
or is_bindings
or is_example:
331 cmake_path = os.path.join(directory,
"CMakeLists.txt")
332 while not os.path.exists(cmake_path):
333 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
334 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
337 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
338 cmake_contents = f.read()
342 if os.path.basename(file)
not in cmake_contents:
343 unused_sources.add(file)
347 "win32-system-wall-clock-ms.cc",
349 for exception
in exceptions:
350 for unused_source
in unused_sources:
351 if os.path.basename(unused_source) == exception:
352 unused_sources.remove(unused_source)
355 self.assertListEqual([], list(unused_sources))
359 Test if all utils source files are being used in their respective CMakeLists.txt
362 unused_sources = set()
365 is_module =
"src" in directory
or "contrib" in directory
366 if os.sep +
"utils" not in directory
or is_module:
371 cmake_path = os.path.join(directory,
"CMakeLists.txt")
372 while not os.path.exists(cmake_path):
373 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
374 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
377 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
378 cmake_contents = f.read()
382 if os.path.basename(file)
not in cmake_contents:
383 unused_sources.add(file)
385 self.assertListEqual([], list(unused_sources))
390 ns-3 tests related to dependencies
395 Checks if headers from different modules (src/A, contrib/B) that are included by
396 the current module (src/C) source files correspond to the list of linked modules
398 LIBRARIES_TO_LINK A (missing B)
402 headers_to_modules = {}
403 module_paths = glob.glob(ns3_path +
"/src/*/") + glob.glob(ns3_path +
"/contrib/*/")
405 for path
in module_paths:
407 cmake_path = os.path.join(path,
"CMakeLists.txt")
408 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
409 cmake_contents = f.readlines()
411 module_name = os.path.relpath(path, ns3_path)
412 module_name_nodir = module_name.replace(
"src/",
"").replace(
"contrib/",
"")
413 modules[module_name_nodir] = {
417 "included_headers": set(),
418 "included_libraries": set(),
422 for line
in cmake_contents:
423 source_file_path = re.findall(
r"\b(?:[^\s]+\.[ch]{1,2})\b", line.strip())
424 if not source_file_path:
426 source_file_path = source_file_path[0]
427 base_name = os.path.basename(source_file_path)
428 if not os.path.exists(os.path.join(path, source_file_path)):
431 if ".h" in source_file_path:
433 modules[module_name_nodir][
"headers"].add(base_name)
434 modules[module_name_nodir][
"sources"].add(base_name)
437 headers_to_modules[base_name] = module_name_nodir
439 if ".cc" in source_file_path:
441 modules[module_name_nodir][
"sources"].add(base_name)
443 if ".cc" in source_file_path
or ".h" in source_file_path:
445 source_file = os.path.join(ns3_path, module_name, source_file_path)
446 with open(source_file,
"r", encoding=
"utf-8")
as f:
447 source_contents = f.read()
448 modules[module_name_nodir][
"included_headers"].update(
450 lambda x: x.replace(
"ns3/",
""),
451 re.findall(
'#include.*["|<](.*)["|>]', source_contents),
457 modules[module_name_nodir][
"libraries"].update(
458 re.findall(
r"\${lib(.*?)}",
"".join(cmake_contents))
460 modules[module_name_nodir][
"libraries"] = list(
463 not in [
"raries_to_link", module_name_nodir, module_name_nodir +
"-obj"],
464 modules[module_name_nodir][
"libraries"],
469 all_project_headers = set(headers_to_modules.keys())
472 print(file=sys.stderr)
473 for module
in sorted(modules):
474 external_headers = modules[module][
"included_headers"].difference(all_project_headers)
475 project_headers_included = modules[module][
"included_headers"].difference(
478 modules[module][
"included_libraries"] = set(
479 [headers_to_modules[x]
for x
in project_headers_included]
480 ).difference({module})
482 diff = modules[module][
"included_libraries"].difference(modules[module][
"libraries"])
485 def recursive_check_dependencies(checked_module):
487 for module_to_link
in modules[checked_module][
"included_libraries"]:
488 modules[checked_module][
"included_libraries"] = set(
489 modules[checked_module][
"included_libraries"]
490 ) - set(modules[module_to_link][
"included_libraries"])
492 for module_to_link
in modules[checked_module][
"included_libraries"]:
493 recursive_check_dependencies(module_to_link)
496 def is_implicitly_linked(searched_module, current_module):
497 if len(modules[current_module][
"included_libraries"]) == 0:
499 if searched_module
in modules[current_module][
"included_libraries"]:
501 for module
in modules[current_module][
"included_libraries"]:
502 if is_implicitly_linked(searched_module, module):
506 from itertools
import combinations
508 implicitly_linked = set()
509 for dep1, dep2
in combinations(modules[checked_module][
"included_libraries"], 2):
510 if is_implicitly_linked(dep1, dep2):
511 implicitly_linked.add(dep1)
512 if is_implicitly_linked(dep2, dep1):
513 implicitly_linked.add(dep2)
515 modules[checked_module][
"included_libraries"] = (
516 set(modules[checked_module][
"included_libraries"]) - implicitly_linked
519 for module
in modules:
520 recursive_check_dependencies(module)
523 for module
in sorted(modules):
526 minimal_linking_set =
", ".join(modules[module][
"included_libraries"])
527 unnecessarily_linked =
", ".join(
528 set(modules[module][
"libraries"]) - set(modules[module][
"included_libraries"])
530 missing_linked =
", ".join(
531 set(modules[module][
"included_libraries"]) - set(modules[module][
"libraries"])
533 if unnecessarily_linked:
534 print(f
"Module '{module}' unnecessarily linked: {unnecessarily_linked}.")
536 print(f
"Module '{module}' missing linked: {missing_linked}.")
537 if unnecessarily_linked
or missing_linked:
538 print(f
"Module '{module}' minimal linking set: {minimal_linking_set}.")
539 self.assertTrue(
True)
544 ns-3 tests to check if the source code, whitespaces and CMake formatting
545 are according to the coding style
555 Import GitRepo and load the original diff state of the repository before the tests
558 if not NS3StyleTestCase.starting_diff:
559 if shutil.which(
"git")
is None:
560 self.skipTest(
"Git is not available")
566 self.skipTest(
"GitPython is not available")
569 repo = Repo(ns3_path)
570 except git.exc.InvalidGitRepositoryError:
571 self.skipTest(
"ns-3 directory does not contain a .git directory")
573 hcommit = repo.head.commit
574 NS3StyleTestCase.starting_diff = hcommit.diff(
None)
575 NS3StyleTestCase.repo = repo
577 if NS3StyleTestCase.starting_diff
is None:
578 self.skipTest(
"Unmet dependencies")
582 Check if there is any difference between tracked file after
583 applying cmake-format
587 for required_program
in [
"cmake",
"cmake-format"]:
588 if shutil.which(required_program)
is None:
589 self.skipTest(
"%s was not found" % required_program)
592 return_code, stdout, stderr =
run_ns3(
"configure")
593 self.assertEqual(return_code, 0)
596 return_code, stdout, stderr =
run_ns3(
"build cmake-format")
597 self.assertEqual(return_code, 0)
600 return_code, stdout, stderr =
run_ns3(
"clean")
601 self.assertEqual(return_code, 0)
604 new_diff = NS3StyleTestCase.repo.head.commit.diff(
None)
605 self.assertEqual(NS3StyleTestCase.starting_diff, new_diff)
610 ns3 tests related to generic options
615 Clean configuration/build artifacts before common commands
624 Test not passing any arguments to
627 return_code, stdout, stderr =
run_ns3(
"")
628 self.assertEqual(return_code, 1)
629 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
633 Test only passing --quiet argument to ns3
636 return_code, stdout, stderr =
run_ns3(
"--quiet")
637 self.assertEqual(return_code, 1)
638 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
642 Test only passing 'show config' argument to ns3
645 return_code, stdout, stderr =
run_ns3(
"show config")
646 self.assertEqual(return_code, 1)
647 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
651 Test only passing 'show profile' argument to ns3
654 return_code, stdout, stderr =
run_ns3(
"show profile")
655 self.assertEqual(return_code, 1)
656 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
660 Test only passing 'show version' argument to ns3
663 return_code, stdout, stderr =
run_ns3(
"show version")
664 self.assertEqual(return_code, 1)
665 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
670 ns3 tests related to build profiles
675 Clean configuration/build artifacts before testing configuration settings
687 return_code, stdout, stderr =
run_ns3(
688 'configure -G "{generator}" -d debug --enable-verbose'
690 self.assertEqual(return_code, 0)
691 self.assertIn(
"Build profile : debug", stdout)
692 self.assertIn(
"Build files have been written to", stdout)
695 return_code, stdout, stderr =
run_ns3(
"build core")
696 self.assertEqual(return_code, 0)
697 self.assertIn(
"Built target core", stdout)
700 self.assertGreater(len(libraries), 0)
701 self.assertIn(
"core-debug", libraries[0])
705 Test the release build
708 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d release')
709 self.assertEqual(return_code, 0)
710 self.assertIn(
"Build profile : release", stdout)
711 self.assertIn(
"Build files have been written to", stdout)
715 Test the optimized build
718 return_code, stdout, stderr =
run_ns3(
719 'configure -G "{generator}" -d optimized --enable-verbose'
721 self.assertEqual(return_code, 0)
722 self.assertIn(
"Build profile : optimized", stdout)
723 self.assertIn(
"Build files have been written to", stdout)
726 return_code, stdout, stderr =
run_ns3(
"build core")
727 self.assertEqual(return_code, 0)
728 self.assertIn(
"Built target core", stdout)
731 self.assertGreater(len(libraries), 0)
732 self.assertIn(
"core-optimized", libraries[0])
736 Test a build type with a typo
739 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d Optimized')
740 self.assertEqual(return_code, 2)
741 self.assertIn(
"invalid choice: 'Optimized'", stderr)
745 Test a build type with another typo
748 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d OPTIMIZED')
749 self.assertEqual(return_code, 2)
750 self.assertIn(
"invalid choice: 'OPTIMIZED'", stderr)
754 Replace settings set by default (e.g. ASSERT/LOGs enabled in debug builds and disabled in default ones)
757 return_code, _, _ =
run_ns3(
"clean")
758 self.assertEqual(return_code, 0)
760 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run -d debug')
761 self.assertEqual(return_code, 0)
763 "-DCMAKE_BUILD_TYPE=debug -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON -DNS3_NATIVE_OPTIMIZATIONS=OFF",
767 return_code, stdout, stderr =
run_ns3(
768 'configure -G "{generator}" --dry-run -d debug --disable-asserts --disable-logs --disable-werror'
770 self.assertEqual(return_code, 0)
772 "-DCMAKE_BUILD_TYPE=debug -DNS3_NATIVE_OPTIMIZATIONS=OFF -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF",
776 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run')
777 self.assertEqual(return_code, 0)
779 "-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF -DNS3_NATIVE_OPTIMIZATIONS=OFF",
783 return_code, stdout, stderr =
run_ns3(
784 'configure -G "{generator}" --dry-run --enable-asserts --enable-logs --enable-werror'
786 self.assertEqual(return_code, 0)
788 "-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",
795 Generic test case with basic function inherited by more complex tests.
800 Check if configuration for release mode worked normally
801 @param return_code: return code from CMake
802 @param stdout: output from CMake.
803 @param stderr: error from CMake.
806 self.assertEqual(return_code, 0)
807 self.assertIn(
"Build profile : release", stdout)
808 self.assertIn(
"Build files have been written to", stdout)
809 self.assertNotIn(
"uninitialized variable", stderr)
813 Clean configuration/build artifacts before testing configuration and build settings
814 After configuring the build as release,
815 check if configuration worked and check expected output files.
820 if os.path.exists(ns3rc_script):
821 os.remove(ns3rc_script)
825 return_code, stdout, stderr =
run_ns3(
826 'configure -G "{generator}" -d release --enable-verbose'
828 self.
config_ok(return_code, stdout, stderr)
831 self.assertTrue(os.path.exists(ns3_lock_filename))
836 self.assertTrue(os.path.exists(ns3_lock_filename))
843 Test ns3 configuration options
848 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
855 Test enabling and disabling examples
858 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
861 self.
config_ok(return_code, stdout, stderr)
868 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
871 self.
config_ok(return_code, stdout, stderr)
878 Test enabling and disabling tests
882 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-tests')
883 self.
config_ok(return_code, stdout, stderr)
886 return_code, stdout, stderr =
run_ns3(
"build core-test")
889 self.assertEqual(return_code, 0)
890 self.assertIn(
"Built target core-test", stdout)
893 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-tests')
894 self.
config_ok(return_code, stdout, stderr)
897 return_code, stdout, stderr =
run_ns3(
"build core-test")
900 self.assertEqual(return_code, 1)
901 self.assertIn(
"Target to build does not exist: core-test", stdout)
905 Test enabling specific modules
909 return_code, stdout, stderr =
run_ns3(
910 "configure -G \"{generator}\" --enable-modules='network;wifi'"
912 self.
config_ok(return_code, stdout, stderr)
918 self.assertIn(
"ns3-network", enabled_modules)
919 self.assertIn(
"ns3-wifi", enabled_modules)
922 return_code, stdout, stderr =
run_ns3(
923 "configure -G \"{generator}\" --enable-modules='core'"
925 self.
config_ok(return_code, stdout, stderr)
929 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
930 self.
config_ok(return_code, stdout, stderr)
937 Test disabling specific modules
941 return_code, stdout, stderr =
run_ns3(
942 "configure -G \"{generator}\" --disable-modules='lte;wimax'"
944 self.
config_ok(return_code, stdout, stderr)
948 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
949 self.assertNotIn(
"ns3-lte", enabled_modules)
950 self.assertNotIn(
"ns3-wimax", enabled_modules)
953 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
954 self.
config_ok(return_code, stdout, stderr)
961 Test enabling comma-separated (waf-style) examples
965 return_code, stdout, stderr =
run_ns3(
966 "configure -G \"{generator}\" --enable-modules='network,wifi'"
968 self.
config_ok(return_code, stdout, stderr)
973 self.assertIn(
"ns3-network", enabled_modules)
974 self.assertIn(
"ns3-wifi", enabled_modules)
977 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
978 self.
config_ok(return_code, stdout, stderr)
985 Test disabling comma-separated (waf-style) examples
989 return_code, stdout, stderr =
run_ns3(
990 "configure -G \"{generator}\" --disable-modules='lte,mpi'"
992 self.
config_ok(return_code, stdout, stderr)
996 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
997 self.assertNotIn(
"ns3-lte", enabled_modules)
998 self.assertNotIn(
"ns3-mpi", enabled_modules)
1001 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
1002 self.
config_ok(return_code, stdout, stderr)
1009 Test loading settings from the ns3rc config file
1015 ns3rc_python_template =
"# ! /usr/bin/env python\
1017 # A list of the modules that will be enabled when ns-3 is run.\
1018 # Modules that depend on the listed modules will be enabled also.\
1020 # All modules can be enabled by choosing 'all_modules'.\
1021 modules_enabled = [{modules}]\
1023 # Set this equal to true if you want examples to be run.\
1024 examples_enabled = {examples}\
1026 # Set this equal to true if you want tests to be run.\
1027 tests_enabled = {tests}\
1031 ns3rc_cmake_template =
"set(ns3rc_tests_enabled {tests})\
1032 \nset(ns3rc_examples_enabled {examples})\
1033 \nset(ns3rc_enabled_modules {modules})\
1037 ns3rc_templates = {
"python": ns3rc_python_template,
"cmake": ns3rc_cmake_template}
1039 def __init__(self, type_ns3rc):
1043 def format(self, **args):
1045 if self.
type ==
"cmake":
1047 args[
"modules"].replace(
"'",
"").replace(
'"',
"").replace(
",",
" ")
1049 args[
"examples"] =
"ON" if args[
"examples"] ==
"True" else "OFF"
1050 args[
"tests"] =
"ON" if args[
"tests"] ==
"True" else "OFF"
1052 formatted_string = ns3rc_str.ns3rc_templates[self.
type].format(**args)
1055 return formatted_string
1059 return ns3rc_str.ns3rc_templates.keys()
1061 for ns3rc_type
in ns3rc_str.types():
1063 ns3rc_template = ns3rc_str(ns3rc_type)
1066 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1067 f.write(ns3rc_template.format(modules=
"'lte'", examples=
"False", tests=
"True"))
1071 return_code, stdout, stderr =
run_ns3(
1072 'configure -G "{generator}" -d release --enable-verbose'
1074 self.
config_ok(return_code, stdout, stderr)
1079 self.assertIn(
"ns3-lte", enabled_modules)
1081 self.assertLessEqual(
1086 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1087 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
1090 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1091 self.
config_ok(return_code, stdout, stderr)
1096 self.assertIn(
"ns3-wifi", enabled_modules)
1101 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1103 ns3rc_template.format(
1104 modules=
"'core','network'", examples=
"True", tests=
"False"
1109 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1110 self.
config_ok(return_code, stdout, stderr)
1115 self.assertIn(
"ns3-core", enabled_modules)
1116 self.assertIn(
"ns3-network", enabled_modules)
1122 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1123 if ns3rc_type ==
"python":
1125 ns3rc_template.format(
1126 modules=
"""'core', #comment
1130 'network', 'internet','wimax'""",
1137 ns3rc_template.format(
1138 modules=
"'core', 'lte', 'network', 'internet', 'wimax'",
1144 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1145 self.
config_ok(return_code, stdout, stderr)
1150 self.assertIn(
"ns3-core", enabled_modules)
1151 self.assertIn(
"ns3-internet", enabled_modules)
1152 self.assertIn(
"ns3-lte", enabled_modules)
1153 self.assertIn(
"ns3-wimax", enabled_modules)
1158 os.remove(ns3rc_script)
1161 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1162 self.
config_ok(return_code, stdout, stderr)
1171 Test dry-run (printing commands to be executed instead of running them)
1177 for positional_command
in [
"configure",
"build",
"clean"]:
1178 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
1179 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
1181 self.assertEqual(return_code, return_code1)
1182 self.assertEqual(stdout, stdout1)
1183 self.assertEqual(stderr, stderr1)
1188 run_ns3(
'configure -G "{generator}" -d release --enable-verbose')
1189 run_ns3(
"build scratch-simulator")
1192 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
1193 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
1194 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
1195 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
1198 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
1199 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
1203 if "scratch-simulator" in program
and "subdir" not in program:
1204 scratch_path = program
1210 self.assertIn(scratch_path, stdout0)
1214 self.assertIn(
"Built target", stdout1)
1215 self.assertNotIn(scratch_path, stdout1)
1218 self.assertIn(
"The following commands would be executed:", stdout2)
1219 self.assertIn(scratch_path, stdout2)
1222 self.assertNotIn(
"Finished executing the following commands:", stdout3)
1223 self.assertNotIn(scratch_path, stdout3)
1227 Test if ns3 is propagating back the return code from the executables called with the run command
1231 return_code, _, _ =
run_ns3(
"clean")
1232 self.assertEqual(return_code, 0)
1234 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-examples --enable-tests')
1235 self.assertEqual(return_code, 0)
1238 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
1239 self.assertEqual(return_code, 0)
1242 return_code, stdout, stderr =
run_ns3(
1243 'run "test-runner --test-name=command-line" --no-build'
1245 self.assertEqual(return_code, 0)
1248 return_code, stdout, stderr =
run_ns3(
1249 'run "test-runner --test-name=command-line" --no-build',
1250 env={
"NS_COMMANDLINE_INTROSPECTION":
".."},
1252 self.assertNotEqual(return_code, 0)
1255 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
1256 with open(sigsegv_example,
"w", encoding=
"utf-8")
as f:
1259 int main (int argc, char *argv[])
1261 char *s = "hello world"; *s = 'H';
1266 return_code, stdout, stderr =
run_ns3(
"run sigsegv")
1268 self.assertEqual(return_code, 4294967295)
1269 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1271 self.assertEqual(return_code, 245)
1272 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1275 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1276 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1279 #include "ns3/core-module.h"
1281 using namespace ns3;
1282 int main (int argc, char *argv[])
1289 return_code, stdout, stderr =
run_ns3(
"run abort")
1291 self.assertNotEqual(return_code, 0)
1292 self.assertIn(
"abort-default.exe' returned non-zero exit status", stdout)
1294 self.assertEqual(return_code, 250)
1295 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
1297 os.remove(sigsegv_example)
1298 os.remove(abort_example)
1302 Test passing 'show config' argument to ns3 to get the configuration table
1305 return_code, stdout, stderr =
run_ns3(
"show config")
1306 self.assertEqual(return_code, 0)
1307 self.assertIn(
"Summary of ns-3 settings", stdout)
1311 Test passing 'show profile' argument to ns3 to get the build profile
1314 return_code, stdout, stderr =
run_ns3(
"show profile")
1315 self.assertEqual(return_code, 0)
1316 self.assertIn(
"Build profile: release", stdout)
1320 Test passing 'show version' argument to ns3 to get the build version
1323 if shutil.which(
"git")
is None:
1324 self.skipTest(
"git is not available")
1326 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-build-version')
1327 self.assertEqual(return_code, 0)
1329 return_code, stdout, stderr =
run_ns3(
"show version")
1330 self.assertEqual(return_code, 0)
1331 self.assertIn(
"ns-3 version:", stdout)
1335 Test if CMake target names for scratches and ns3 shortcuts
1336 are working correctly
1343 "scratch/subdir1/main.cc",
1344 "scratch/subdir2/main.cc",
1345 "scratch/main.test.dots.in.name.cc",
1347 backup_files = [
"scratch/.main.cc"]
1350 for path
in test_files + backup_files:
1351 filepath = os.path.join(ns3_path, path)
1352 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
1353 with open(filepath,
"w", encoding=
"utf-8")
as f:
1355 f.write(
"int main (int argc, char *argv[]){}")
1364 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1365 self.assertEqual(return_code, 1)
1368 empty =
"scratch/empty.cc"
1370 test_files.remove(empty)
1371 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1372 self.assertEqual(return_code, 0)
1375 for path
in test_files + backup_files:
1376 path = path.replace(
".cc",
"")
1379 "--build . --target %s -j %d" % (path.replace(
"/",
"_"), num_threads),
1380 cwd=os.path.join(ns3_path,
"cmake-cache"),
1382 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
1383 if "main" in path
and ".main" not in path:
1384 self.assertEqual(return_code1, 0)
1385 self.assertEqual(return_code2, 0)
1387 self.assertEqual(return_code1, 2)
1388 self.assertEqual(return_code2, 1)
1391 for path
in test_files:
1392 path = path.replace(
".cc",
"")
1393 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
1395 self.assertEqual(return_code, 0)
1397 self.assertEqual(return_code, 1)
1401 container.execute(
"apt-get update")
1402 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
1405 "./ns3 configure --enable-modules=core,network,internet -- -DCMAKE_CXX_COMPILER=/usr/bin/g++"
1407 except DockerException
as e:
1409 for path
in test_files:
1410 path = path.replace(
".cc",
"")
1412 container.execute(f
"./ns3 run {path}")
1413 except DockerException
as e:
1419 for path
in test_files + backup_files:
1420 source_absolute_path = os.path.join(ns3_path, path)
1421 os.remove(source_absolute_path)
1422 if "empty" in path
or ".main" in path:
1424 filename = os.path.basename(path).replace(
".cc",
"")
1425 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
1426 if os.path.exists(executable_absolute_path):
1427 executable_name = list(
1428 filter(
lambda x: filename
in x, os.listdir(executable_absolute_path))
1431 os.remove(os.path.join(executable_absolute_path, executable_name))
1432 if not os.listdir(os.path.dirname(path)):
1433 os.rmdir(os.path.dirname(source_absolute_path))
1435 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1436 self.assertEqual(return_code, 0)
1440 Test if ns3 is inserting additional arguments by MPICH and OpenMPI to run on the CI
1444 if shutil.which(
"mpiexec")
is None or win32:
1445 self.skipTest(
"Mpi is not available")
1447 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1448 self.assertEqual(return_code, 0)
1452 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
1453 self.assertEqual(return_code, 0)
1456 sample_simulator_path = list(filter(
lambda x:
"sample-simulator" in x, executables))[0]
1458 mpi_command =
'--dry-run run sample-simulator --command-template="mpiexec -np 2 %s"'
1459 non_mpi_command =
'--dry-run run sample-simulator --command-template="echo %s"'
1462 return_code, stdout, stderr =
run_ns3(mpi_command)
1463 self.assertEqual(return_code, 0)
1464 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1467 return_code, stdout, stderr =
run_ns3(mpi_command)
1468 self.assertEqual(return_code, 0)
1469 if os.getenv(
"USER",
"") ==
"root":
1470 if shutil.which(
"ompi_info"):
1472 "mpiexec --allow-run-as-root --oversubscribe -np 2 %s" % sample_simulator_path,
1477 "mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout
1480 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1483 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1484 self.assertEqual(return_code, 0)
1485 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1488 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1489 self.assertEqual(return_code, 0)
1490 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1492 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1493 self.assertEqual(return_code, 0)
1497 Test if CMake and ns3 fail in the expected ways when:
1498 - examples from modules or general examples fail if they depend on a
1499 library with a name shorter than 4 characters or are disabled when
1500 a library is nonexistent
1501 - a module library passes the configuration but fails to build due to
1505 os.makedirs(
"contrib/borked", exist_ok=
True)
1506 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1509 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1511 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1512 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1517 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1518 LIBRARIES_TO_LINK ${libcore} %s
1521 % invalid_or_nonexistent_library
1524 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1525 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1526 self.assertEqual(return_code, 0)
1527 elif invalid_or_nonexistent_library
in [
"lib"]:
1528 self.assertEqual(return_code, 1)
1529 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1533 return_code, stdout, stderr =
run_ns3(
"build borked")
1534 if invalid_or_nonexistent_library
in [
""]:
1535 self.assertEqual(return_code, 0)
1536 elif invalid_or_nonexistent_library
in [
"lib"]:
1537 self.assertEqual(return_code, 2)
1538 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1539 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1540 self.assertEqual(return_code, 2)
1541 if "lld" in stdout + stderr:
1543 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1545 elif "mold" in stdout + stderr:
1546 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1549 "library not found for -l%s" % invalid_or_nonexistent_library, stderr
1552 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1560 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1565 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1566 LIBRARIES_TO_LINK ${libcore}
1570 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1571 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1576 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1577 LIBRARIES_TO_LINK ${libborked} %s
1580 % invalid_or_nonexistent_library
1583 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1584 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1585 self.assertEqual(return_code, 0)
1586 elif invalid_or_nonexistent_library
in [
"lib"]:
1587 self.assertEqual(return_code, 1)
1588 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1592 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1593 if invalid_or_nonexistent_library
in [
""]:
1594 self.assertEqual(return_code, 0)
1595 elif invalid_or_nonexistent_library
in [
"libf"]:
1596 self.assertEqual(return_code, 2)
1597 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1598 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1599 self.assertEqual(return_code, 1)
1600 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1604 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1608 Test if CMake can properly handle modules containing "lib",
1609 which is used internally as a prefix for module libraries
1613 os.makedirs(
"contrib/calibre", exist_ok=
True)
1614 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1617 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1619 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1624 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1625 LIBRARIES_TO_LINK ${libcore}
1630 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1633 self.assertEqual(return_code, 0)
1636 self.assertIn(
"calibre", stdout)
1640 self.assertNotIn(
"care", stdout)
1642 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1646 return_code, stdout, stderr =
run_ns3(
"build calibre")
1647 self.assertEqual(return_code, 0)
1650 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1654 Test if CMake performance tracing works and produces the
1655 cmake_performance_trace.log file
1658 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1659 if os.path.exists(cmake_performance_trace_log):
1660 os.remove(cmake_performance_trace_log)
1662 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1663 self.assertEqual(return_code, 0)
1665 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1668 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1671 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1675 Check if ENABLE_BUILD_VERSION and version.cache are working
1683 container.execute(
"apt-get update")
1684 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1687 container.execute(
"./ns3 clean")
1690 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1693 if os.path.exists(version_cache_file):
1694 os.remove(version_cache_file)
1698 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1699 except DockerException:
1701 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1704 version_cache_contents = (
1705 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1706 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1707 "VERSION_DIRTY_FLAG = '0'\n"
1708 "VERSION_MAJOR = '3'\n"
1709 "VERSION_MINOR = '0'\n"
1710 "VERSION_PATCH = '0'\n"
1711 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1712 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1713 "VERSION_TAG_DISTANCE = '0'\n"
1714 "VERSION_BUILD_PROFILE = 'debug'\n"
1716 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1717 version.write(version_cache_contents)
1720 container.execute(
"./ns3 clean")
1721 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1722 container.execute(
"./ns3 build core")
1723 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1726 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1727 self.assertEqual(version.read(), version_cache_contents)
1732 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1734 container.execute(
"apt-get install -y git")
1735 container.execute(
"./ns3 clean")
1736 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1737 container.execute(
"./ns3 build core")
1738 except DockerException:
1740 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1741 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1744 container.execute(
"./ns3 clean")
1745 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1746 container.execute(
"./ns3 build core")
1747 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1748 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1749 self.assertNotEqual(version.read(), version_cache_contents)
1752 if os.path.exists(version_cache_file):
1753 os.remove(version_cache_file)
1757 Test filtering in examples and tests from specific modules
1761 return_code, stdout, stderr =
run_ns3(
1762 'configure -G "{generator}" --enable-examples --enable-tests'
1764 self.
config_ok(return_code, stdout, stderr)
1769 return_code, stdout, stderr =
run_ns3(
1770 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1772 self.
config_ok(return_code, stdout, stderr)
1778 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1780 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1783 return_code, stdout, stderr =
run_ns3(
1784 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1786 self.
config_ok(return_code, stdout, stderr)
1794 return_code, stdout, stderr =
run_ns3(
1795 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1797 self.
config_ok(return_code, stdout, stderr)
1805 Check if fast linkers LLD and Mold are correctly found and configured
1812 container.execute(
"apt-get update")
1813 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1816 container.execute(
"./ns3 configure -G Ninja")
1819 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1821 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1823 self.assertIn(
"-fuse-ld=lld", f.read())
1827 container.execute(
"./ns3 build core")
1828 except DockerException:
1829 self.assertTrue(
False,
"Build with lld failed")
1832 if not os.path.exists(f
"./mold-1.4.2-{arch}-linux.tar.gz"):
1834 f
"wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch}-linux.tar.gz"
1837 f
"tar xzfC mold-1.4.2-{arch}-linux.tar.gz /usr/local --strip-components=1"
1842 container.execute(
"./ns3 configure -G Ninja")
1845 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1847 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1849 self.assertIn(
"-fuse-ld=mold", f.read())
1853 container.execute(
"./ns3 build core")
1854 except DockerException:
1855 self.assertTrue(
False,
"Build with mold failed")
1858 os.remove(f
"./mold-1.4.2-{arch}-linux.tar.gz")
1861 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1864 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1866 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1868 self.assertNotIn(
"-fuse-ld=mold", f.read())
1872 Check if NS3_CLANG_TIMETRACE feature is working
1873 Clang's -ftime-trace plus ClangAnalyzer report
1879 container.execute(
"apt-get update")
1880 container.execute(
"apt-get install -y python3 ninja-build cmake clang-18")
1885 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1887 except DockerException
as e:
1888 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1890 container.execute(
"apt-get install -y git")
1895 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1897 except DockerException
as e:
1898 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1901 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1902 if os.path.exists(time_trace_report_path):
1903 os.remove(time_trace_report_path)
1907 container.execute(
"./ns3 build timeTraceReport")
1908 except DockerException
as e:
1909 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1912 self.assertTrue(os.path.exists(time_trace_report_path))
1916 container.execute(
"apt-get install -y g++")
1917 container.execute(
"apt-get remove -y clang-18")
1921 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1924 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1926 except DockerException
as e:
1927 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1931 Check if NS3_NINJA_TRACE feature is working
1932 Ninja's .ninja_log conversion to about://tracing
1933 json format conversion with Ninjatracing
1939 container.execute(
"apt-get update")
1940 container.execute(
"apt-get remove -y g++")
1941 container.execute(
"apt-get install -y python3 cmake g++-11 clang-18")
1946 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1948 except DockerException
as e:
1949 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1954 container.execute(
"apt-get install -y ninja-build")
1958 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1960 except DockerException
as e:
1961 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1963 container.execute(
"apt-get install -y git")
1967 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18"
1969 except DockerException
as e:
1970 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1973 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1974 if os.path.exists(ninja_trace_path):
1975 os.remove(ninja_trace_path)
1978 container.execute(
"./ns3 build core")
1982 container.execute(
"./ns3 build ninjaTrace")
1983 except DockerException
as e:
1984 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1987 self.assertTrue(os.path.exists(ninja_trace_path))
1988 trace_size = os.stat(ninja_trace_path).st_size
1989 os.remove(ninja_trace_path)
1996 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-18 -DNS3_CLANG_TIMETRACE=ON"
1998 except DockerException
as e:
1999 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
2002 container.execute(
"./ns3 build core")
2006 container.execute(
"./ns3 build ninjaTrace")
2007 except DockerException
as e:
2008 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
2010 self.assertTrue(os.path.exists(ninja_trace_path))
2011 timetrace_size = os.stat(ninja_trace_path).st_size
2012 os.remove(ninja_trace_path)
2015 self.assertGreater(timetrace_size, trace_size)
2019 Check if precompiled headers are being enabled correctly.
2029 container.execute(
"apt-get update")
2030 container.execute(
"apt-get install -y python3 cmake ccache g++")
2032 container.execute(
"./ns3 configure")
2033 except DockerException
as e:
2034 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2038 Check for regressions in test object build.
2041 return_code, stdout, stderr =
run_ns3(
"configure")
2042 self.assertEqual(return_code, 0)
2044 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2045 self.assertFalse(os.path.exists(test_module_cache))
2047 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2048 self.assertEqual(return_code, 0)
2049 self.assertTrue(os.path.exists(test_module_cache))
2053 Check for regressions in a bare ns-3 configuration.
2060 container.execute(
"apt-get update")
2061 container.execute(
"apt-get install -y python3 cmake g++")
2065 stdout = container.execute(
"./ns3 configure -d release")
2066 except DockerException
as e:
2068 self.
config_ok(return_code, stdout, stdout)
2075 Tests ns3 regarding building the project
2080 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2089 Try building the core library
2092 return_code, stdout, stderr =
run_ns3(
"build core")
2093 self.assertEqual(return_code, 0)
2094 self.assertIn(
"Built target core", stdout)
2098 Try building core-test library without tests enabled
2102 return_code, stdout, stderr =
run_ns3(
"build core-test")
2103 self.assertEqual(return_code, 1)
2104 self.assertIn(
"Target to build does not exist: core-test", stdout)
2108 Try building the project:
2111 return_code, stdout, stderr =
run_ns3(
"build")
2112 self.assertEqual(return_code, 0)
2113 self.assertIn(
"Built target", stdout)
2115 self.assertTrue(os.path.exists(program), program)
2116 self.assertIn(cmake_build_project_command, stdout)
2120 Try hiding task lines
2123 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2124 self.assertEqual(return_code, 0)
2125 self.assertIn(cmake_build_project_command, stdout)
2129 Try removing an essential file to break the build
2133 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2134 attribute_cc_bak_path = attribute_cc_path +
".bak"
2135 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2138 return_code, stdout, stderr =
run_ns3(
"build")
2139 self.assertNotEqual(return_code, 0)
2142 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2145 return_code, stdout, stderr =
run_ns3(
"build")
2146 self.assertEqual(return_code, 0)
2150 Test if changing the version file affects the library names
2156 version_file = os.sep.join([ns3_path,
"VERSION"])
2157 with open(version_file,
"w", encoding=
"utf-8")
as f:
2161 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2162 self.
config_ok(return_code, stdout, stderr)
2165 return_code, stdout, stderr =
run_ns3(
"build")
2166 self.assertEqual(return_code, 0)
2167 self.assertIn(
"Built target", stdout)
2173 for program
in new_programs:
2174 self.assertTrue(os.path.exists(program))
2181 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2182 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2183 for library
in new_libraries:
2184 self.assertNotIn(
"libns3-dev", library)
2185 self.assertIn(
"libns3-00", library)
2186 self.assertTrue(os.path.exists(library))
2189 with open(version_file,
"w", encoding=
"utf-8")
as f:
2194 Try setting a different output directory and if everything is
2195 in the right place and still working correctly
2200 return_code, stdout, stderr =
run_ns3(
"build")
2201 self.assertEqual(return_code, 0)
2216 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2217 relative_path = os.sep.join([
"build",
"release"])
2218 for different_out_dir
in [absolute_path, relative_path]:
2219 return_code, stdout, stderr =
run_ns3(
2220 'configure -G "{generator}" --out=%s' % different_out_dir
2222 self.
config_ok(return_code, stdout, stderr)
2224 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2233 for program
in new_programs:
2234 self.assertTrue(os.path.exists(program))
2238 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2239 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2240 for library
in new_libraries:
2241 self.assertTrue(os.path.exists(library))
2244 shutil.rmtree(absolute_path)
2247 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2248 self.
config_ok(return_code, stdout, stderr)
2250 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2259 for program
in new_programs:
2260 self.assertTrue(os.path.exists(program))
2265 for library
in libraries:
2266 self.assertTrue(os.path.exists(library))
2270 Tries setting a ns3 version, then installing it.
2271 After that, tries searching for ns-3 with CMake's find_package(ns3).
2272 Finally, tries using core library in a 3rd-party project
2277 for library
in libraries:
2281 version_file = os.sep.join([ns3_path,
"VERSION"])
2282 with open(version_file,
"w", encoding=
"utf-8")
as f:
2286 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2287 return_code, stdout, stderr =
run_ns3(
2288 'configure -G "{generator}" --prefix=%s' % install_prefix
2290 self.
config_ok(return_code, stdout, stderr)
2301 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2302 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2306 installed_libraries_list =
";".join(installed_libraries)
2307 for library
in libraries:
2308 library_name = os.path.basename(library)
2309 self.assertIn(library_name, installed_libraries_list)
2313 missing_headers = list(
2314 set([os.path.basename(x)
for x
in headers])
2315 - (set([os.path.basename(x)
for x
in installed_headers]))
2317 self.assertEqual(len(missing_headers), 0)
2320 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2321 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2324 #include <ns3/core-module.h>
2325 using namespace ns3;
2328 Simulator::Stop (Seconds (1.0));
2330 Simulator::Destroy ();
2339 for version
in [
"",
"3.01",
"3.00"]:
2340 ns3_import_methods = []
2343 cmake_find_package_import =
"""
2344 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2345 find_package(ns3 {version} COMPONENTS core)
2346 target_link_libraries(test PRIVATE ns3::core)
2348 lib=(
"lib64" if lib64
else "lib"), version=version
2350 ns3_import_methods.append(cmake_find_package_import)
2353 pkgconfig_import =
"""
2354 list(APPEND CMAKE_PREFIX_PATH ./)
2355 include(FindPkgConfig)
2356 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2357 target_link_libraries(test PUBLIC PkgConfig::ns3)
2359 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2361 if shutil.which(
"pkg-config"):
2362 ns3_import_methods.append(pkgconfig_import)
2365 for import_method
in ns3_import_methods:
2366 test_cmake_project = (
2368 cmake_minimum_required(VERSION 3.20..3.20)
2369 project(ns3_consumer CXX)
2370 set(CMAKE_CXX_STANDARD 23)
2371 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2372 add_executable(test main.cpp)
2377 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2378 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2379 f.write(test_cmake_project)
2382 cmake = shutil.which(
"cmake")
2385 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2386 generator=platform_makefiles
2391 if version ==
"3.00":
2392 self.assertEqual(return_code, 1)
2393 if import_method == cmake_find_package_import:
2395 'Could not find a configuration file for package "ns3" that is compatible',
2396 stderr.replace(
"\n",
""),
2398 elif import_method == pkgconfig_import:
2399 self.assertIn(
"not found", stderr.replace(
"\n",
""))
2401 raise Exception(
"Unknown import type")
2403 self.assertEqual(return_code, 0)
2404 self.assertIn(
"Build files", stdout)
2407 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2409 if version ==
"3.00":
2410 self.assertEqual(return_code, 2, msg=stdout + stderr)
2411 self.assertGreater(len(stderr), 0)
2413 self.assertEqual(return_code, 0)
2414 self.assertIn(
"Built target", stdout)
2418 test_program = os.path.join(install_prefix,
"test.exe")
2419 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2421 "PATH": env_sep.join(
2422 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2426 test_program =
"./test"
2429 test_program,
"", cwd=install_prefix, env=env
2431 self.assertEqual(return_code, 0)
2434 return_code, stdout, stderr =
run_ns3(
"uninstall")
2435 self.assertIn(
"Built target uninstall", stdout)
2438 os.remove(version_file)
2439 with open(version_file,
"w", encoding=
"utf-8")
as f:
2444 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2449 "scratch/scratch-simulator":
"scratch-simulator",
2450 "scratch/scratch-simulator.cc":
"scratch-simulator",
2451 "scratch-simulator":
"scratch-simulator",
2452 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2453 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2454 "scratch-subdir":
"subdir_scratch-subdir",
2456 for target_to_run, target_cmake
in targets.items():
2458 build_line =
"target scratch_%s" % target_cmake
2459 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2460 self.assertEqual(return_code, 0)
2461 self.assertIn(build_line, stdout)
2464 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2465 self.assertEqual(return_code, 0)
2466 self.assertIn(build_line, stdout)
2467 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2468 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2472 Test if ns3 can alert correctly in case a shortcut collision happens
2477 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2478 self.assertEqual(return_code, 0)
2481 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2484 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2485 self.assertEqual(return_code, 0)
2488 return_code, stdout, stderr =
run_ns3(
"build second")
2489 self.assertEqual(return_code, 1)
2491 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2492 stdout.replace(os.sep,
"/"),
2496 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2497 self.assertEqual(return_code, 0)
2501 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2502 self.assertEqual(return_code, 0)
2506 return_code, stdout, stderr =
run_ns3(
"run second")
2507 self.assertEqual(return_code, 1)
2509 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2510 stdout.replace(os.sep,
"/"),
2514 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2515 self.assertEqual(return_code, 0)
2518 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2519 self.assertEqual(return_code, 0)
2522 os.remove(
"./scratch/second.cc")
2526 Test if we can build a static ns-3 library and link it to static programs
2529 if (
not win32)
and (arch ==
"aarch64"):
2530 if platform.libc_ver()[0] ==
"glibc":
2531 from packaging.version
import Version
2533 if Version(platform.libc_ver()[1]) < Version(
"2.37"):
2535 "Static linking on ARM64 requires glibc 2.37 where fPIC was enabled (fpic is limited in number of GOT entries)"
2539 return_code, stdout, stderr =
run_ns3(
2540 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2546 self.assertEqual(return_code, 1)
2547 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2550 self.assertEqual(return_code, 0)
2553 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2554 self.assertEqual(return_code, 0)
2555 self.assertIn(
"Built target", stdout)
2561 Test if we can use python bindings
2566 except ModuleNotFoundError:
2567 self.skipTest(
"Cppyy was not found")
2570 return_code, stdout, stderr =
run_ns3(
2571 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2575 self.assertEqual(return_code, 0)
2578 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2579 self.assertEqual(return_code, 0)
2582 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2583 self.assertEqual(return_code, 0)
2587 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2589 self.assertEqual(return_code, 0)
2593 Test if we had regressions with brite, click and openflow modules
2594 that depend on homonymous libraries
2597 if shutil.which(
"git")
is None:
2598 self.skipTest(
"Missing git")
2601 self.skipTest(
"Optional components are not supported on Windows")
2604 return_code, stdout, stderr =
run_ns3(
"configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON")
2605 self.assertEqual(return_code, 0)
2609 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2610 self.assertEqual(return_code, 0)
2614 Test if we can link contrib modules to src modules
2617 if shutil.which(
"git")
is None:
2618 self.skipTest(
"Missing git")
2620 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2621 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2623 if os.path.exists(destination_contrib):
2624 shutil.rmtree(destination_contrib)
2625 if os.path.exists(destination_src):
2626 shutil.rmtree(destination_src)
2630 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2631 destination_contrib,
2634 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2639 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2640 self.assertEqual(return_code, 0)
2643 return_code, stdout, stderr =
run_ns3(
"run source-example")
2644 self.assertEqual(return_code, 0)
2647 shutil.rmtree(destination_contrib)
2648 shutil.rmtree(destination_src)
2653 Tests ns3 usage in more realistic scenarios
2658 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2659 Here examples, tests and documentation are also enabled.
2666 return_code, stdout, stderr =
run_ns3(
2667 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2669 self.
config_ok(return_code, stdout, stderr)
2672 self.assertTrue(os.path.exists(ns3_lock_filename))
2678 self.assertTrue(os.path.exists(ns3_lock_filename))
2685 Try to build the project
2688 return_code, stdout, stderr =
run_ns3(
"build")
2689 self.assertEqual(return_code, 0)
2690 self.assertIn(
"Built target", stdout)
2692 self.assertTrue(os.path.exists(program))
2695 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2696 self.assertIn(cmake_build_project_command, stdout)
2700 Try to build and run test-runner
2703 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2704 self.assertEqual(return_code, 0)
2705 self.assertIn(
"Built target test-runner", stdout)
2710 Try to build and run a library
2713 return_code, stdout, stderr =
run_ns3(
"run core")
2714 self.assertEqual(return_code, 1)
2715 self.assertIn(
"Couldn't find the specified program: core", stderr)
2719 Try to build and run an unknown target
2722 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2723 self.assertEqual(return_code, 1)
2724 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2728 Try to run test-runner without building
2731 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2732 self.assertEqual(return_code, 0)
2734 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2735 self.assertEqual(return_code, 0)
2736 self.assertNotIn(
"Built target test-runner", stdout)
2741 Test ns3 fails to run a library
2744 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2745 self.assertEqual(return_code, 1)
2746 self.assertIn(
"Couldn't find the specified program: core", stderr)
2750 Test ns3 fails to run an unknown program
2753 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2754 self.assertEqual(return_code, 1)
2755 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2759 Test if scratch simulator is executed through gdb and lldb
2762 if shutil.which(
"gdb")
is None:
2763 self.skipTest(
"Missing gdb")
2765 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2766 self.assertEqual(return_code, 0)
2768 return_code, stdout, stderr =
run_ns3(
2769 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2771 self.assertEqual(return_code, 0)
2772 self.assertIn(
"scratch-simulator", stdout)
2774 self.assertIn(
"GNU gdb", stdout)
2776 self.assertIn(
"No debugging symbols found", stdout)
2780 Test if scratch simulator is executed through valgrind
2783 if shutil.which(
"valgrind")
is None:
2784 self.skipTest(
"Missing valgrind")
2786 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2787 self.assertEqual(return_code, 0)
2789 return_code, stdout, stderr =
run_ns3(
2790 "run scratch-simulator --valgrind --verbose --no-build"
2792 self.assertEqual(return_code, 0)
2793 self.assertIn(
"scratch-simulator", stderr)
2794 self.assertIn(
"Memcheck", stderr)
2798 Test the doxygen target that does trigger a full build
2801 if shutil.which(
"doxygen")
is None:
2802 self.skipTest(
"Missing doxygen")
2804 if shutil.which(
"bash")
is None:
2805 self.skipTest(
"Missing bash")
2807 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2809 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2810 for filename
in doxygen_files:
2811 file_path = os.sep.join([doc_folder, filename])
2812 if os.path.exists(file_path):
2813 os.remove(file_path)
2820 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2821 self.assertEqual(return_code, 0)
2823 self.assertIn(
"Built target doxygen", stdout)
2827 Test the doxygen target that doesn't trigger a full build
2830 if shutil.which(
"doxygen")
is None:
2831 self.skipTest(
"Missing doxygen")
2839 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2840 self.assertEqual(return_code, 0)
2842 self.assertIn(
"Built target doxygen-no-build", stdout)
2846 Test every individual target for Sphinx-based documentation
2849 if shutil.which(
"sphinx-build")
is None:
2850 self.skipTest(
"Missing sphinx")
2852 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2855 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2857 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2858 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2859 if os.path.exists(doc_build_folder):
2860 shutil.rmtree(doc_build_folder)
2861 if os.path.exists(doc_temp_folder):
2862 shutil.rmtree(doc_temp_folder)
2865 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2866 self.assertEqual(return_code, 0, target)
2868 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2871 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2872 self.assertTrue(os.path.exists(doc_build_folder))
2875 for build_type
in [
"latex",
"html",
"singlehtml"]:
2876 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2880 Test the documentation target that builds
2881 both doxygen and sphinx based documentation
2884 if shutil.which(
"doxygen")
is None:
2885 self.skipTest(
"Missing doxygen")
2886 if shutil.which(
"sphinx-build")
is None:
2887 self.skipTest(
"Missing sphinx")
2889 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2898 for target
in [
"manual",
"models",
"tutorial"]:
2899 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2900 if os.path.exists(doc_build_folder):
2901 shutil.rmtree(doc_build_folder)
2903 return_code, stdout, stderr =
run_ns3(
"docs all")
2904 self.assertEqual(return_code, 0)
2906 self.assertIn(
"Built target sphinx", stdout)
2908 self.assertIn(
"Built target doxygen", stdout)
2912 Try to set ownership of scratch-simulator from current user to root,
2913 and change execution permissions
2918 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2921 if sudo_password
is None:
2922 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2925 self.assertFalse(enable_sudo
is True)
2928 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2929 self.assertEqual(return_code, 0)
2930 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2932 scratch_simulator_path = list(
2933 filter(
lambda x: x
if "scratch-simulator" in x
else None, self.
ns3_executables)
2935 prev_fstat = os.stat(scratch_simulator_path)
2938 return_code, stdout, stderr =
run_ns3(
2939 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2941 self.assertEqual(return_code, 0)
2942 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2944 fstat = os.stat(scratch_simulator_path)
2950 likely_fuse_mount = (
2951 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2952 )
and prev_fstat.st_uid == 0
2954 if win32
or likely_fuse_mount:
2955 self.skipTest(
"Windows or likely a FUSE mount")
2958 self.assertEqual(fstat.st_uid, 0)
2960 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2964 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2965 self.assertEqual(return_code, 0)
2969 self.assertTrue(enable_sudo)
2973 if os.path.exists(executable):
2974 os.remove(executable)
2977 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2978 self.assertEqual(return_code, 0)
2981 self.assertIn(
"chown root", stdout)
2982 self.assertIn(
"chmod u+s", stdout)
2984 self.assertIn(os.path.basename(executable), stdout)
2987 fstat = os.stat(scratch_simulator_path)
2988 self.assertEqual(fstat.st_uid, 0)
2990 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2995 Check if command template is working
3000 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
3001 self.assertEqual(return_code0, 2)
3002 self.assertIn(
"argument --command-template: expected one argument", stderr0)
3004 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
3005 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
3006 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
3007 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
3008 for stderr
in [stderr1, stderr2, stderr3]:
3009 self.assertIn(
"not all arguments converted during string formatting", stderr)
3012 return_code4, stdout4, _ =
run_ns3(
3013 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
3015 return_code5, stdout5, _ =
run_ns3(
3016 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
3018 self.assertEqual((return_code4, return_code5), (0, 0))
3020 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3021 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3025 Check if all flavors of different argument passing to
3026 executable targets are working
3031 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3032 return_code1, stdout1, stderr1 =
run_ns3(
3033 'run sample-simulator --command-template="%s --help" --verbose'
3035 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3037 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3038 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3039 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3040 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3043 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3044 return_code1, stdout1, stderr1 =
run_ns3(
3045 'run sample-simulator --command-template="%s --help" --no-build'
3047 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3048 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3049 self.assertEqual(stdout0, stdout1)
3050 self.assertEqual(stdout1, stdout2)
3051 self.assertEqual(stderr0, stderr1)
3052 self.assertEqual(stderr1, stderr2)
3055 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3056 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3057 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3059 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3060 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3061 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3062 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3065 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3066 return_code, stdout, stderr =
run_ns3(cmd)
3067 self.assertEqual(return_code, 0)
3073 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3078 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3079 cmd1 =
"run sample-simulator --PrintTypeIds"
3081 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3082 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3083 self.assertEqual((return_code0, return_code1), (1, 1))
3084 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3085 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3089 Test if scratch simulator is executed through lldb
3092 if shutil.which(
"lldb")
is None:
3093 self.skipTest(
"Missing lldb")
3095 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3096 self.assertEqual(return_code, 0)
3098 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3099 self.assertEqual(return_code, 0)
3100 self.assertIn(
"scratch-simulator", stdout)
3101 self.assertIn(
"(lldb) target create", stdout)
3105 Test if CPM and Vcpkg package managers are working properly
3109 return_code, stdout, stderr =
run_ns3(
"clean")
3110 self.assertEqual(return_code, 0)
3113 if os.path.exists(
"vcpkg"):
3114 shutil.rmtree(
"vcpkg")
3117 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3119 if os.path.exists(destination_src):
3120 shutil.rmtree(destination_src)
3124 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3130 container.execute(
"apt-get update")
3131 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3136 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3137 self.skipTest(
"Armadillo is already installed")
3138 except DockerException
as e:
3142 return_code, stdout, stderr =
run_ns3(
"clean")
3143 self.assertEqual(return_code, 0)
3146 container.execute(
"apt-get install -y git")
3151 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3153 except DockerException
as e:
3158 container.execute(
"./ns3 build test-package-managers")
3159 except DockerException
as e:
3163 return_code, stdout, stderr =
run_ns3(
"clean")
3164 self.assertEqual(return_code, 0)
3166 if arch !=
"aarch64":
3168 container.execute(
"apt-get install -y zip unzip tar curl")
3171 container.execute(
"apt-get install -y pkg-config gfortran")
3175 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3176 except DockerException
as e:
3181 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3182 except DockerException
as e:
3187 container.execute(
"./ns3 build test-package-managers")
3188 except DockerException
as e:
3192 if os.path.exists(destination_src):
3193 shutil.rmtree(destination_src)
3198 ns-3 tests to control the quality of the repository over time
3203 Check if images in the docs are above a brightness threshold.
3204 This should prevent screenshots with dark UI themes.
3207 if shutil.which(
"convert")
is None:
3208 self.skipTest(
"Imagemagick was not found")
3210 from pathlib
import Path
3213 image_extensions = [
"png",
"jpg"]
3215 for extension
in image_extensions:
3216 images += list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3217 images += list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3220 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3224 brightness_threshold = 50
3225 for image
in images:
3226 brightness = subprocess.check_output(
3227 imagemagick_get_image_brightness.format(image=image).split()
3229 brightness = float(brightness.decode().strip(
"'\""))
3232 brightness_threshold,
3233 "Image darker than threshold (%d < %d): %s"
3234 % (brightness, brightness_threshold, image),
3239 Check if one of the log statements of examples/tests contains/exposes a bug.
3243 return_code, stdout, stderr =
run_ns3(
3244 'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
3246 self.assertEqual(return_code, 0)
3250 "test.py",
"", python=
True, env={
"TEST_LOGS":
"1"}
3252 self.assertEqual(return_code, 0)
3257 ns-3 complementary tests, allowed to fail, to help control
3258 the quality of the repository over time, by checking the
3259 state of URLs listed and more
3264 Test if all urls in source files are alive
3273 self.skipTest(
"Django URL validators are not available")
3280 urllib3.disable_warnings()
3283 self.skipTest(
"Requests library is not available")
3285 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3288 whitelisted_urls = {
3289 "https://gitlab.com/your-user-name/ns-3-dev",
3290 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3291 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3292 "https://www.nsnam.org/releases/ns-3-x",
3293 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3294 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3295 "https://ns-buildmaster.ee.washington.edu:8010/",
3297 "https://cmake.org/cmake/help/latest/manual/cmake-",
3298 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3300 "http://www.lysator.liu.se/~alla/dia/",
3302 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3303 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3304 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3305 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3306 "https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch",
3307 "http://www.nsnam.org/bugzilla/show_bug.cgi?id=",
3309 "http://www.research.att.com/info/kpv/",
3310 "http://www.research.att.com/~gsf/",
3311 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3312 "http://scan5.coverity.com/cgi-bin/upload.py",
3314 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3315 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3319 files_and_urls = set()
3321 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3322 for root, dirs, files
in os.walk(topdir):
3324 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3327 filepath = os.path.join(root, file)
3330 if not os.path.isfile(filepath):
3334 if file.endswith(
".svg"):
3338 with open(filepath,
"r", encoding=
"utf-8")
as f:
3339 matches = regex.findall(f.read())
3345 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3347 except UnicodeDecodeError:
3348 skipped_files.append(filepath)
3352 for url
in set(urls) - unique_urls - whitelisted_urls:
3353 unique_urls.add(url)
3354 files_and_urls.add((filepath, url))
3357 from django.core.exceptions
import ValidationError
3358 from django.core.validators
import URLValidator
3360 validate_url = URLValidator()
3364 "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"
3368 def test_file_url(args):
3369 test_filepath, test_url = args
3370 dead_link_msg =
None
3374 validate_url(test_url)
3375 except ValidationError:
3376 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3377 except Exception
as e:
3378 self.assertEqual(
False,
True, msg=e.__str__())
3380 if dead_link_msg
is not None:
3381 return dead_link_msg
3389 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3392 if response.status_code
in [200, 301]:
3393 dead_link_msg =
None
3398 if response.status_code
in [302, 308, 500, 503]:
3399 if response.reason.lower()
in [
3401 "moved temporarily",
3402 "permanent redirect",
3404 "service temporarily unavailable",
3406 dead_link_msg =
None
3410 dead_link_msg =
"%s: URL %s: returned code %d" % (
3413 response.status_code,
3415 except requests.exceptions.InvalidURL:
3416 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3417 except requests.exceptions.SSLError:
3418 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3419 except requests.exceptions.TooManyRedirects:
3420 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3421 except Exception
as e:
3423 error_msg = e.args[0].reason.__str__()
3424 except AttributeError:
3425 error_msg = e.args[0]
3426 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3432 return dead_link_msg
3435 from concurrent.futures
import ThreadPoolExecutor
3437 with ThreadPoolExecutor(max_workers=100)
as executor:
3438 dead_links = list(executor.map(test_file_url, list(files_and_urls)))
3441 dead_links = list(sorted(filter(
lambda x: x
is not None, dead_links)))
3442 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3446 Test if all tests can be executed without hitting major memory bugs
3449 return_code, stdout, stderr =
run_ns3(
3450 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3452 self.assertEqual(return_code, 0)
3454 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3455 self.assertEqual(test_return_code, 0)
3464 test_completeness = {
3466 NS3UnusedSourcesTestCase,
3470 NS3CommonSettingsTestCase,
3471 NS3ConfigureBuildProfileTestCase,
3472 NS3ConfigureTestCase,
3473 NS3BuildBaseTestCase,
3474 NS3ExpectedUseTestCase,
3477 NS3UnusedSourcesTestCase,
3479 NS3CommonSettingsTestCase,
3480 NS3ConfigureBuildProfileTestCase,
3481 NS3ConfigureTestCase,
3482 NS3BuildBaseTestCase,
3483 NS3ExpectedUseTestCase,
3484 NS3QualityControlTestCase,
3487 NS3DependenciesTestCase,
3488 NS3QualityControlThatCanFailTestCase,
3494 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3495 parser.add_argument(
3496 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3498 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3499 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3500 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3501 parser.add_argument(
"-f",
"--failfast", action=
"store_true", default=
False)
3502 args = parser.parse_args(sys.argv[1:])
3504 loader = unittest.TestLoader()
3505 suite = unittest.TestSuite()
3508 for testCase
in test_completeness[args.completeness]:
3509 suite.addTests(loader.loadTestsFromTestCase(testCase))
3514 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3516 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3517 tests_to_remove = set(tests) - set(tests_to_run)
3518 for test_to_remove
in tests_to_remove:
3519 suite._tests.remove(tests[test_to_remove])
3522 if args.resume_from_test_name:
3524 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3525 keys = list(tests.keys())
3527 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3528 suite._tests.remove(tests[keys[0]])
3532 ns3rc_script_bak = ns3rc_script +
".bak"
3533 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3534 shutil.move(ns3rc_script, ns3rc_script_bak)
3537 runner = unittest.TextTestRunner(failfast=args.failfast, verbosity=1
if args.quiet
else 2)
3541 if os.path.exists(ns3rc_script_bak):
3542 shutil.move(ns3rc_script_bak, ns3rc_script)
3545if __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.