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
224 volumes=[(ns3_path,
"/ns-3-dev")],
228 def split_exec(docker_container, cmd):
229 return docker_container._execute(cmd.split(), workdir=
"/ns-3-dev")
236 Return the managed container when entiring the block "with DockerContainerManager() as container"
237 @param self: the current DockerContainerManager instance
238 @return container managed by DockerContainerManager.
244 Clean up the managed container at the end of the block "with DockerContainerManager() as container"
245 @param self: the current DockerContainerManager instance
246 @param exc_type: unused parameter
247 @param exc_val: unused parameter
248 @param exc_tb: unused parameter
257 ns-3 tests related to checking if source files were left behind, not being used by CMake
261 directory_and_files = {}
265 Scan all C++ source files and add them to a list based on their path
268 for root, dirs, files
in os.walk(ns3_path):
269 if "gitlab-ci-local" in root:
272 if name.endswith(
".cc"):
273 path = os.path.join(root, name)
274 directory = os.path.dirname(path)
281 Test if all example source files are being used in their respective CMakeLists.txt
284 unused_sources = set()
287 if os.sep +
"examples" not in example_directory:
291 if not os.path.exists(os.path.join(example_directory,
"CMakeLists.txt")):
296 os.path.join(example_directory,
"CMakeLists.txt"),
"r", encoding=
"utf-8"
298 cmake_contents = f.read()
303 if os.path.basename(file).replace(
".cc",
"")
not in cmake_contents:
304 unused_sources.add(file)
306 self.assertListEqual([], list(unused_sources))
310 Test if all module source files are being used in their respective CMakeLists.txt
313 unused_sources = set()
316 is_not_module =
not (
"src" in directory
or "contrib" in directory)
317 is_example = os.sep +
"examples" in directory
318 is_bindings = os.sep +
"bindings" in directory
320 if is_not_module
or is_bindings
or is_example:
325 cmake_path = os.path.join(directory,
"CMakeLists.txt")
326 while not os.path.exists(cmake_path):
327 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
328 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
331 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
332 cmake_contents = f.read()
336 if os.path.basename(file)
not in cmake_contents:
337 unused_sources.add(file)
341 "win32-system-wall-clock-ms.cc",
343 for exception
in exceptions:
344 for unused_source
in unused_sources:
345 if os.path.basename(unused_source) == exception:
346 unused_sources.remove(unused_source)
349 self.assertListEqual([], list(unused_sources))
353 Test if all utils source files are being used in their respective CMakeLists.txt
356 unused_sources = set()
359 is_module =
"src" in directory
or "contrib" in directory
360 if os.sep +
"utils" not in directory
or is_module:
365 cmake_path = os.path.join(directory,
"CMakeLists.txt")
366 while not os.path.exists(cmake_path):
367 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
368 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
371 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
372 cmake_contents = f.read()
376 if os.path.basename(file)
not in cmake_contents:
377 unused_sources.add(file)
379 self.assertListEqual([], list(unused_sources))
384 ns-3 tests related to dependencies
389 Checks if headers from different modules (src/A, contrib/B) that are included by
390 the current module (src/C) source files correspond to the list of linked modules
392 LIBRARIES_TO_LINK A (missing B)
396 headers_to_modules = {}
397 module_paths = glob.glob(ns3_path +
"/src/*/") + glob.glob(ns3_path +
"/contrib/*/")
399 for path
in module_paths:
401 cmake_path = os.path.join(path,
"CMakeLists.txt")
402 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
403 cmake_contents = f.readlines()
405 module_name = os.path.relpath(path, ns3_path)
406 module_name_nodir = module_name.replace(
"src/",
"").replace(
"contrib/",
"")
407 modules[module_name_nodir] = {
411 "included_headers": set(),
412 "included_libraries": set(),
416 for line
in cmake_contents:
417 source_file_path = re.findall(
r"\b(?:[^\s]+\.[ch]{1,2})\b", line.strip())
418 if not source_file_path:
420 source_file_path = source_file_path[0]
421 base_name = os.path.basename(source_file_path)
422 if not os.path.exists(os.path.join(path, source_file_path)):
425 if ".h" in source_file_path:
427 modules[module_name_nodir][
"headers"].add(base_name)
428 modules[module_name_nodir][
"sources"].add(base_name)
431 headers_to_modules[base_name] = module_name_nodir
433 if ".cc" in source_file_path:
435 modules[module_name_nodir][
"sources"].add(base_name)
437 if ".cc" in source_file_path
or ".h" in source_file_path:
439 source_file = os.path.join(ns3_path, module_name, source_file_path)
440 with open(source_file,
"r", encoding=
"utf-8")
as f:
441 source_contents = f.read()
442 modules[module_name_nodir][
"included_headers"].update(
444 lambda x: x.replace(
"ns3/",
""),
445 re.findall(
'#include.*["|<](.*)["|>]', source_contents),
451 modules[module_name_nodir][
"libraries"].update(
452 re.findall(
r"\${lib(.*?)}",
"".join(cmake_contents))
454 modules[module_name_nodir][
"libraries"] = list(
457 not in [
"raries_to_link", module_name_nodir, module_name_nodir +
"-obj"],
458 modules[module_name_nodir][
"libraries"],
463 all_project_headers = set(headers_to_modules.keys())
466 print(file=sys.stderr)
467 for module
in sorted(modules):
468 external_headers = modules[module][
"included_headers"].difference(all_project_headers)
469 project_headers_included = modules[module][
"included_headers"].difference(
472 modules[module][
"included_libraries"] = set(
473 [headers_to_modules[x]
for x
in project_headers_included]
474 ).difference({module})
476 diff = modules[module][
"included_libraries"].difference(modules[module][
"libraries"])
479 def recursive_check_dependencies(checked_module):
481 for module_to_link
in modules[checked_module][
"included_libraries"]:
482 modules[checked_module][
"included_libraries"] = set(
483 modules[checked_module][
"included_libraries"]
484 ) - set(modules[module_to_link][
"included_libraries"])
486 for module_to_link
in modules[checked_module][
"included_libraries"]:
487 recursive_check_dependencies(module_to_link)
490 def is_implicitly_linked(searched_module, current_module):
491 if len(modules[current_module][
"included_libraries"]) == 0:
493 if searched_module
in modules[current_module][
"included_libraries"]:
495 for module
in modules[current_module][
"included_libraries"]:
496 if is_implicitly_linked(searched_module, module):
500 from itertools
import combinations
502 implicitly_linked = set()
503 for dep1, dep2
in combinations(modules[checked_module][
"included_libraries"], 2):
504 if is_implicitly_linked(dep1, dep2):
505 implicitly_linked.add(dep1)
506 if is_implicitly_linked(dep2, dep1):
507 implicitly_linked.add(dep2)
509 modules[checked_module][
"included_libraries"] = (
510 set(modules[checked_module][
"included_libraries"]) - implicitly_linked
513 for module
in modules:
514 recursive_check_dependencies(module)
517 for module
in sorted(modules):
520 minimal_linking_set =
", ".join(modules[module][
"included_libraries"])
521 unnecessarily_linked =
", ".join(
522 set(modules[module][
"libraries"]) - set(modules[module][
"included_libraries"])
524 missing_linked =
", ".join(
525 set(modules[module][
"included_libraries"]) - set(modules[module][
"libraries"])
527 if unnecessarily_linked:
528 print(f
"Module '{module}' unnecessarily linked: {unnecessarily_linked}.")
530 print(f
"Module '{module}' missing linked: {missing_linked}.")
531 if unnecessarily_linked
or missing_linked:
532 print(f
"Module '{module}' minimal linking set: {minimal_linking_set}.")
533 self.assertTrue(
True)
538 ns-3 tests to check if the source code, whitespaces and CMake formatting
539 are according to the coding style
549 Import GitRepo and load the original diff state of the repository before the tests
552 if not NS3StyleTestCase.starting_diff:
553 if shutil.which(
"git")
is None:
554 self.skipTest(
"Git is not available")
560 self.skipTest(
"GitPython is not available")
563 repo = Repo(ns3_path)
564 except git.exc.InvalidGitRepositoryError:
565 self.skipTest(
"ns-3 directory does not contain a .git directory")
567 hcommit = repo.head.commit
568 NS3StyleTestCase.starting_diff = hcommit.diff(
None)
569 NS3StyleTestCase.repo = repo
571 if NS3StyleTestCase.starting_diff
is None:
572 self.skipTest(
"Unmet dependencies")
576 Check if there is any difference between tracked file after
577 applying cmake-format
581 for required_program
in [
"cmake",
"cmake-format"]:
582 if shutil.which(required_program)
is None:
583 self.skipTest(
"%s was not found" % required_program)
586 return_code, stdout, stderr =
run_ns3(
"configure")
587 self.assertEqual(return_code, 0)
590 return_code, stdout, stderr =
run_ns3(
"build cmake-format")
591 self.assertEqual(return_code, 0)
594 return_code, stdout, stderr =
run_ns3(
"clean")
595 self.assertEqual(return_code, 0)
598 new_diff = NS3StyleTestCase.repo.head.commit.diff(
None)
599 self.assertEqual(NS3StyleTestCase.starting_diff, new_diff)
604 ns3 tests related to generic options
609 Clean configuration/build artifacts before common commands
618 Test not passing any arguments to
621 return_code, stdout, stderr =
run_ns3(
"")
622 self.assertEqual(return_code, 1)
623 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
627 Test only passing --quiet argument to ns3
630 return_code, stdout, stderr =
run_ns3(
"--quiet")
631 self.assertEqual(return_code, 1)
632 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
636 Test only passing 'show config' argument to ns3
639 return_code, stdout, stderr =
run_ns3(
"show config")
640 self.assertEqual(return_code, 1)
641 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
645 Test only passing 'show profile' argument to ns3
648 return_code, stdout, stderr =
run_ns3(
"show profile")
649 self.assertEqual(return_code, 1)
650 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
654 Test only passing 'show version' argument to ns3
657 return_code, stdout, stderr =
run_ns3(
"show version")
658 self.assertEqual(return_code, 1)
659 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
664 ns3 tests related to build profiles
669 Clean configuration/build artifacts before testing configuration settings
681 return_code, stdout, stderr =
run_ns3(
682 'configure -G "{generator}" -d debug --enable-verbose'
684 self.assertEqual(return_code, 0)
685 self.assertIn(
"Build profile : debug", stdout)
686 self.assertIn(
"Build files have been written to", stdout)
689 return_code, stdout, stderr =
run_ns3(
"build core")
690 self.assertEqual(return_code, 0)
691 self.assertIn(
"Built target core", stdout)
694 self.assertGreater(len(libraries), 0)
695 self.assertIn(
"core-debug", libraries[0])
699 Test the release build
702 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d release')
703 self.assertEqual(return_code, 0)
704 self.assertIn(
"Build profile : release", stdout)
705 self.assertIn(
"Build files have been written to", stdout)
709 Test the optimized build
712 return_code, stdout, stderr =
run_ns3(
713 'configure -G "{generator}" -d optimized --enable-verbose'
715 self.assertEqual(return_code, 0)
716 self.assertIn(
"Build profile : optimized", stdout)
717 self.assertIn(
"Build files have been written to", stdout)
720 return_code, stdout, stderr =
run_ns3(
"build core")
721 self.assertEqual(return_code, 0)
722 self.assertIn(
"Built target core", stdout)
725 self.assertGreater(len(libraries), 0)
726 self.assertIn(
"core-optimized", libraries[0])
730 Test a build type with a typo
733 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d Optimized')
734 self.assertEqual(return_code, 2)
735 self.assertIn(
"invalid choice: 'Optimized'", stderr)
739 Test a build type with another typo
742 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d OPTIMIZED')
743 self.assertEqual(return_code, 2)
744 self.assertIn(
"invalid choice: 'OPTIMIZED'", stderr)
748 Replace settings set by default (e.g. ASSERT/LOGs enabled in debug builds and disabled in default ones)
751 return_code, _, _ =
run_ns3(
"clean")
752 self.assertEqual(return_code, 0)
754 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run -d debug')
755 self.assertEqual(return_code, 0)
757 "-DCMAKE_BUILD_TYPE=debug -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON -DNS3_NATIVE_OPTIMIZATIONS=OFF",
761 return_code, stdout, stderr =
run_ns3(
762 'configure -G "{generator}" --dry-run -d debug --disable-asserts --disable-logs --disable-werror'
764 self.assertEqual(return_code, 0)
766 "-DCMAKE_BUILD_TYPE=debug -DNS3_NATIVE_OPTIMIZATIONS=OFF -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF",
770 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run')
771 self.assertEqual(return_code, 0)
773 "-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF -DNS3_NATIVE_OPTIMIZATIONS=OFF",
777 return_code, stdout, stderr =
run_ns3(
778 'configure -G "{generator}" --dry-run --enable-asserts --enable-logs --enable-werror'
780 self.assertEqual(return_code, 0)
782 "-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",
789 Generic test case with basic function inherited by more complex tests.
794 Check if configuration for release mode worked normally
795 @param return_code: return code from CMake
796 @param stdout: output from CMake.
797 @param stderr: error from CMake.
800 self.assertEqual(return_code, 0)
801 self.assertIn(
"Build profile : release", stdout)
802 self.assertIn(
"Build files have been written to", stdout)
803 self.assertNotIn(
"uninitialized variable", stderr)
807 Clean configuration/build artifacts before testing configuration and build settings
808 After configuring the build as release,
809 check if configuration worked and check expected output files.
814 if os.path.exists(ns3rc_script):
815 os.remove(ns3rc_script)
819 return_code, stdout, stderr =
run_ns3(
820 'configure -G "{generator}" -d release --enable-verbose'
822 self.
config_ok(return_code, stdout, stderr)
825 self.assertTrue(os.path.exists(ns3_lock_filename))
830 self.assertTrue(os.path.exists(ns3_lock_filename))
837 Test ns3 configuration options
842 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
849 Test enabling and disabling examples
852 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
855 self.
config_ok(return_code, stdout, stderr)
862 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
865 self.
config_ok(return_code, stdout, stderr)
872 Test enabling and disabling tests
876 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-tests')
877 self.
config_ok(return_code, stdout, stderr)
880 return_code, stdout, stderr =
run_ns3(
"build core-test")
883 self.assertEqual(return_code, 0)
884 self.assertIn(
"Built target core-test", stdout)
887 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-tests')
888 self.
config_ok(return_code, stdout, stderr)
891 return_code, stdout, stderr =
run_ns3(
"build core-test")
894 self.assertEqual(return_code, 1)
895 self.assertIn(
"Target to build does not exist: core-test", stdout)
899 Test enabling specific modules
903 return_code, stdout, stderr =
run_ns3(
904 "configure -G \"{generator}\" --enable-modules='network;wifi'"
906 self.
config_ok(return_code, stdout, stderr)
912 self.assertIn(
"ns3-network", enabled_modules)
913 self.assertIn(
"ns3-wifi", enabled_modules)
916 return_code, stdout, stderr =
run_ns3(
917 "configure -G \"{generator}\" --enable-modules='core'"
919 self.
config_ok(return_code, stdout, stderr)
923 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
924 self.
config_ok(return_code, stdout, stderr)
931 Test disabling specific modules
935 return_code, stdout, stderr =
run_ns3(
936 "configure -G \"{generator}\" --disable-modules='lte;wimax'"
938 self.
config_ok(return_code, stdout, stderr)
943 self.assertNotIn(
"ns3-lte", enabled_modules)
944 self.assertNotIn(
"ns3-wimax", enabled_modules)
947 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
948 self.
config_ok(return_code, stdout, stderr)
955 Test enabling comma-separated (waf-style) examples
959 return_code, stdout, stderr =
run_ns3(
960 "configure -G \"{generator}\" --enable-modules='network,wifi'"
962 self.
config_ok(return_code, stdout, stderr)
967 self.assertIn(
"ns3-network", enabled_modules)
968 self.assertIn(
"ns3-wifi", enabled_modules)
971 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
972 self.
config_ok(return_code, stdout, stderr)
979 Test disabling comma-separated (waf-style) examples
983 return_code, stdout, stderr =
run_ns3(
984 "configure -G \"{generator}\" --disable-modules='lte,mpi'"
986 self.
config_ok(return_code, stdout, stderr)
991 self.assertNotIn(
"ns3-lte", enabled_modules)
992 self.assertNotIn(
"ns3-mpi", enabled_modules)
995 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
996 self.
config_ok(return_code, stdout, stderr)
1003 Test loading settings from the ns3rc config file
1009 ns3rc_python_template =
"# ! /usr/bin/env python\
1011 # A list of the modules that will be enabled when ns-3 is run.\
1012 # Modules that depend on the listed modules will be enabled also.\
1014 # All modules can be enabled by choosing 'all_modules'.\
1015 modules_enabled = [{modules}]\
1017 # Set this equal to true if you want examples to be run.\
1018 examples_enabled = {examples}\
1020 # Set this equal to true if you want tests to be run.\
1021 tests_enabled = {tests}\
1025 ns3rc_cmake_template =
"set(ns3rc_tests_enabled {tests})\
1026 \nset(ns3rc_examples_enabled {examples})\
1027 \nset(ns3rc_enabled_modules {modules})\
1031 ns3rc_templates = {
"python": ns3rc_python_template,
"cmake": ns3rc_cmake_template}
1033 def __init__(self, type_ns3rc):
1037 def format(self, **args):
1039 if self.
type ==
"cmake":
1041 args[
"modules"].replace(
"'",
"").replace(
'"',
"").replace(
",",
" ")
1043 args[
"examples"] =
"ON" if args[
"examples"] ==
"True" else "OFF"
1044 args[
"tests"] =
"ON" if args[
"tests"] ==
"True" else "OFF"
1046 formatted_string = ns3rc_str.ns3rc_templates[self.
type].format(**args)
1049 return formatted_string
1053 return ns3rc_str.ns3rc_templates.keys()
1055 for ns3rc_type
in ns3rc_str.types():
1057 ns3rc_template = ns3rc_str(ns3rc_type)
1060 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1061 f.write(ns3rc_template.format(modules=
"'lte'", examples=
"False", tests=
"True"))
1065 return_code, stdout, stderr =
run_ns3(
1066 'configure -G "{generator}" -d release --enable-verbose'
1068 self.
config_ok(return_code, stdout, stderr)
1073 self.assertIn(
"ns3-lte", enabled_modules)
1075 self.assertLessEqual(
1080 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1081 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
1084 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1085 self.
config_ok(return_code, stdout, stderr)
1090 self.assertIn(
"ns3-wifi", enabled_modules)
1095 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1097 ns3rc_template.format(
1098 modules=
"'core','network'", examples=
"True", tests=
"False"
1103 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1104 self.
config_ok(return_code, stdout, stderr)
1109 self.assertIn(
"ns3-core", enabled_modules)
1110 self.assertIn(
"ns3-network", enabled_modules)
1116 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1117 if ns3rc_type ==
"python":
1119 ns3rc_template.format(
1120 modules=
"""'core', #comment
1124 'network', 'internet','wimax'""",
1131 ns3rc_template.format(
1132 modules=
"'core', 'lte', 'network', 'internet', 'wimax'",
1138 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1139 self.
config_ok(return_code, stdout, stderr)
1144 self.assertIn(
"ns3-core", enabled_modules)
1145 self.assertIn(
"ns3-internet", enabled_modules)
1146 self.assertIn(
"ns3-lte", enabled_modules)
1147 self.assertIn(
"ns3-wimax", enabled_modules)
1152 os.remove(ns3rc_script)
1155 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1156 self.
config_ok(return_code, stdout, stderr)
1165 Test dry-run (printing commands to be executed instead of running them)
1171 for positional_command
in [
"configure",
"build",
"clean"]:
1172 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
1173 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
1175 self.assertEqual(return_code, return_code1)
1176 self.assertEqual(stdout, stdout1)
1177 self.assertEqual(stderr, stderr1)
1182 run_ns3(
'configure -G "{generator}" -d release --enable-verbose')
1183 run_ns3(
"build scratch-simulator")
1186 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
1187 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
1188 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
1189 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
1192 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
1193 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
1197 if "scratch-simulator" in program
and "subdir" not in program:
1198 scratch_path = program
1204 self.assertIn(scratch_path, stdout0)
1208 self.assertIn(
"Built target", stdout1)
1209 self.assertNotIn(scratch_path, stdout1)
1212 self.assertIn(
"The following commands would be executed:", stdout2)
1213 self.assertIn(scratch_path, stdout2)
1216 self.assertNotIn(
"Finished executing the following commands:", stdout3)
1217 self.assertNotIn(scratch_path, stdout3)
1221 Test if ns3 is propagating back the return code from the executables called with the run command
1225 return_code, _, _ =
run_ns3(
"clean")
1226 self.assertEqual(return_code, 0)
1228 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-examples --enable-tests')
1229 self.assertEqual(return_code, 0)
1232 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
1233 self.assertEqual(return_code, 0)
1236 return_code, stdout, stderr =
run_ns3(
1237 'run "test-runner --test-name=command-line" --no-build'
1239 self.assertEqual(return_code, 0)
1242 return_code, stdout, stderr =
run_ns3(
1243 'run "test-runner --test-name=command-line" --no-build',
1244 env={
"NS_COMMANDLINE_INTROSPECTION":
".."},
1246 self.assertNotEqual(return_code, 0)
1249 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
1250 with open(sigsegv_example,
"w", encoding=
"utf-8")
as f:
1253 int main (int argc, char *argv[])
1255 char *s = "hello world"; *s = 'H';
1260 return_code, stdout, stderr =
run_ns3(
"run sigsegv")
1262 self.assertEqual(return_code, 4294967295)
1263 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1265 self.assertEqual(return_code, 245)
1266 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1269 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1270 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1273 #include "ns3/core-module.h"
1275 using namespace ns3;
1276 int main (int argc, char *argv[])
1283 return_code, stdout, stderr =
run_ns3(
"run abort")
1285 self.assertNotEqual(return_code, 0)
1286 self.assertIn(
"abort-default.exe' returned non-zero exit status", stdout)
1288 self.assertEqual(return_code, 250)
1289 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
1291 os.remove(sigsegv_example)
1292 os.remove(abort_example)
1296 Test passing 'show config' argument to ns3 to get the configuration table
1299 return_code, stdout, stderr =
run_ns3(
"show config")
1300 self.assertEqual(return_code, 0)
1301 self.assertIn(
"Summary of ns-3 settings", stdout)
1305 Test passing 'show profile' argument to ns3 to get the build profile
1308 return_code, stdout, stderr =
run_ns3(
"show profile")
1309 self.assertEqual(return_code, 0)
1310 self.assertIn(
"Build profile: release", stdout)
1314 Test passing 'show version' argument to ns3 to get the build version
1317 if shutil.which(
"git")
is None:
1318 self.skipTest(
"git is not available")
1320 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-build-version')
1321 self.assertEqual(return_code, 0)
1323 return_code, stdout, stderr =
run_ns3(
"show version")
1324 self.assertEqual(return_code, 0)
1325 self.assertIn(
"ns-3 version:", stdout)
1329 Test if CMake target names for scratches and ns3 shortcuts
1330 are working correctly
1337 "scratch/subdir1/main.cc",
1338 "scratch/subdir2/main.cc",
1339 "scratch/main.test.dots.in.name.cc",
1341 backup_files = [
"scratch/.main.cc"]
1344 for path
in test_files + backup_files:
1345 filepath = os.path.join(ns3_path, path)
1346 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
1347 with open(filepath,
"w", encoding=
"utf-8")
as f:
1349 f.write(
"int main (int argc, char *argv[]){}")
1358 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1359 self.assertEqual(return_code, 1)
1362 empty =
"scratch/empty.cc"
1364 test_files.remove(empty)
1365 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1366 self.assertEqual(return_code, 0)
1369 for path
in test_files + backup_files:
1370 path = path.replace(
".cc",
"")
1373 "--build . --target %s -j %d" % (path.replace(
"/",
"_"), num_threads),
1374 cwd=os.path.join(ns3_path,
"cmake-cache"),
1376 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
1377 if "main" in path
and ".main" not in path:
1378 self.assertEqual(return_code1, 0)
1379 self.assertEqual(return_code2, 0)
1381 self.assertEqual(return_code1, 2)
1382 self.assertEqual(return_code2, 1)
1385 for path
in test_files:
1386 path = path.replace(
".cc",
"")
1387 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
1389 self.assertEqual(return_code, 0)
1391 self.assertEqual(return_code, 1)
1395 container.execute(
"apt-get update")
1396 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
1399 "./ns3 configure --enable-modules=core,network,internet -- -DCMAKE_CXX_COMPILER=/usr/bin/g++"
1401 except DockerException
as e:
1403 for path
in test_files:
1404 path = path.replace(
".cc",
"")
1406 container.execute(f
"./ns3 run {path}")
1407 except DockerException
as e:
1413 for path
in test_files + backup_files:
1414 source_absolute_path = os.path.join(ns3_path, path)
1415 os.remove(source_absolute_path)
1416 if "empty" in path
or ".main" in path:
1418 filename = os.path.basename(path).replace(
".cc",
"")
1419 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
1420 if os.path.exists(executable_absolute_path):
1421 executable_name = list(
1422 filter(
lambda x: filename
in x, os.listdir(executable_absolute_path))
1425 os.remove(os.path.join(executable_absolute_path, executable_name))
1426 if not os.listdir(os.path.dirname(path)):
1427 os.rmdir(os.path.dirname(source_absolute_path))
1429 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1430 self.assertEqual(return_code, 0)
1434 Test if ns3 is inserting additional arguments by MPICH and OpenMPI to run on the CI
1438 if shutil.which(
"mpiexec")
is None or win32:
1439 self.skipTest(
"Mpi is not available")
1441 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1442 self.assertEqual(return_code, 0)
1446 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
1447 self.assertEqual(return_code, 0)
1450 sample_simulator_path = list(filter(
lambda x:
"sample-simulator" in x, executables))[0]
1452 mpi_command =
'--dry-run run sample-simulator --command-template="mpiexec -np 2 %s"'
1453 non_mpi_command =
'--dry-run run sample-simulator --command-template="echo %s"'
1456 return_code, stdout, stderr =
run_ns3(mpi_command)
1457 self.assertEqual(return_code, 0)
1458 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1461 return_code, stdout, stderr =
run_ns3(mpi_command)
1462 self.assertEqual(return_code, 0)
1463 if os.getenv(
"USER",
"") ==
"root":
1464 if shutil.which(
"ompi_info"):
1466 "mpiexec --allow-run-as-root --oversubscribe -np 2 %s" % sample_simulator_path,
1471 "mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout
1474 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1477 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1478 self.assertEqual(return_code, 0)
1479 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1482 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1483 self.assertEqual(return_code, 0)
1484 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1486 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1487 self.assertEqual(return_code, 0)
1491 Test if CMake and ns3 fail in the expected ways when:
1492 - examples from modules or general examples fail if they depend on a
1493 library with a name shorter than 4 characters or are disabled when
1494 a library is nonexistent
1495 - a module library passes the configuration but fails to build due to
1499 os.makedirs(
"contrib/borked", exist_ok=
True)
1500 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1503 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1505 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1506 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1511 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1512 LIBRARIES_TO_LINK ${libcore} %s
1515 % invalid_or_nonexistent_library
1518 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1519 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1520 self.assertEqual(return_code, 0)
1521 elif invalid_or_nonexistent_library
in [
"lib"]:
1522 self.assertEqual(return_code, 1)
1523 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1527 return_code, stdout, stderr =
run_ns3(
"build borked")
1528 if invalid_or_nonexistent_library
in [
""]:
1529 self.assertEqual(return_code, 0)
1530 elif invalid_or_nonexistent_library
in [
"lib"]:
1531 self.assertEqual(return_code, 2)
1532 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1533 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1534 self.assertEqual(return_code, 2)
1535 if "lld" in stdout + stderr:
1537 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1539 elif "mold" in stdout + stderr:
1540 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1543 "library not found for -l%s" % invalid_or_nonexistent_library, stderr
1546 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1554 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1559 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1560 LIBRARIES_TO_LINK ${libcore}
1564 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1565 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1570 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1571 LIBRARIES_TO_LINK ${libborked} %s
1574 % invalid_or_nonexistent_library
1577 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1578 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1579 self.assertEqual(return_code, 0)
1580 elif invalid_or_nonexistent_library
in [
"lib"]:
1581 self.assertEqual(return_code, 1)
1582 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1586 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1587 if invalid_or_nonexistent_library
in [
""]:
1588 self.assertEqual(return_code, 0)
1589 elif invalid_or_nonexistent_library
in [
"libf"]:
1590 self.assertEqual(return_code, 2)
1591 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1592 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1593 self.assertEqual(return_code, 1)
1594 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1598 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1602 Test if CMake can properly handle modules containing "lib",
1603 which is used internally as a prefix for module libraries
1607 os.makedirs(
"contrib/calibre", exist_ok=
True)
1608 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1611 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1613 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1618 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1619 LIBRARIES_TO_LINK ${libcore}
1624 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1627 self.assertEqual(return_code, 0)
1630 self.assertIn(
"calibre", stdout)
1634 self.assertNotIn(
"care", stdout)
1636 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1640 return_code, stdout, stderr =
run_ns3(
"build calibre")
1641 self.assertEqual(return_code, 0)
1644 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1648 Test if CMake performance tracing works and produces the
1649 cmake_performance_trace.log file
1652 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1653 if os.path.exists(cmake_performance_trace_log):
1654 os.remove(cmake_performance_trace_log)
1656 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1657 self.assertEqual(return_code, 0)
1659 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1662 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1665 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1669 Check if ENABLE_BUILD_VERSION and version.cache are working
1677 container.execute(
"apt-get update")
1678 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1681 container.execute(
"./ns3 clean")
1684 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1687 if os.path.exists(version_cache_file):
1688 os.remove(version_cache_file)
1692 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1693 except DockerException:
1695 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1698 version_cache_contents = (
1699 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1700 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1701 "VERSION_DIRTY_FLAG = '0'\n"
1702 "VERSION_MAJOR = '3'\n"
1703 "VERSION_MINOR = '0'\n"
1704 "VERSION_PATCH = '0'\n"
1705 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1706 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1707 "VERSION_TAG_DISTANCE = '0'\n"
1708 "VERSION_BUILD_PROFILE = 'debug'\n"
1710 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1711 version.write(version_cache_contents)
1714 container.execute(
"./ns3 clean")
1715 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1716 container.execute(
"./ns3 build core")
1717 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1720 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1721 self.assertEqual(version.read(), version_cache_contents)
1726 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1728 container.execute(
"apt-get install -y git")
1729 container.execute(
"./ns3 clean")
1730 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1731 container.execute(
"./ns3 build core")
1732 except DockerException:
1734 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1735 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1738 container.execute(
"./ns3 clean")
1739 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1740 container.execute(
"./ns3 build core")
1741 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1742 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1743 self.assertNotEqual(version.read(), version_cache_contents)
1746 if os.path.exists(version_cache_file):
1747 os.remove(version_cache_file)
1751 Test filtering in examples and tests from specific modules
1755 return_code, stdout, stderr =
run_ns3(
1756 'configure -G "{generator}" --enable-examples --enable-tests'
1758 self.
config_ok(return_code, stdout, stderr)
1763 return_code, stdout, stderr =
run_ns3(
1764 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1766 self.
config_ok(return_code, stdout, stderr)
1772 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1774 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1777 return_code, stdout, stderr =
run_ns3(
1778 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1780 self.
config_ok(return_code, stdout, stderr)
1788 return_code, stdout, stderr =
run_ns3(
1789 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1791 self.
config_ok(return_code, stdout, stderr)
1799 Check if fast linkers LLD and Mold are correctly found and configured
1806 container.execute(
"apt-get update")
1807 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1810 container.execute(
"./ns3 configure -G Ninja")
1813 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1815 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1817 self.assertIn(
"-fuse-ld=lld", f.read())
1821 container.execute(
"./ns3 build core")
1822 except DockerException:
1823 self.assertTrue(
False,
"Build with lld failed")
1826 if not os.path.exists(f
"./mold-1.4.2-{arch}-linux.tar.gz"):
1828 f
"wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-{arch}-linux.tar.gz"
1831 f
"tar xzfC mold-1.4.2-{arch}-linux.tar.gz /usr/local --strip-components=1"
1836 container.execute(
"./ns3 configure -G Ninja")
1839 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1841 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1843 self.assertIn(
"-fuse-ld=mold", f.read())
1847 container.execute(
"./ns3 build core")
1848 except DockerException:
1849 self.assertTrue(
False,
"Build with mold failed")
1852 os.remove(f
"./mold-1.4.2-{arch}-linux.tar.gz")
1855 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1858 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1860 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1862 self.assertNotIn(
"-fuse-ld=mold", f.read())
1866 Check if NS3_CLANG_TIMETRACE feature is working
1867 Clang's -ftime-trace plus ClangAnalyzer report
1873 container.execute(
"apt-get update")
1874 container.execute(
"apt-get install -y python3 ninja-build cmake clang-12")
1879 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -DNS3_CLANG_TIMETRACE=ON"
1881 except DockerException
as e:
1882 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1884 container.execute(
"apt-get install -y git")
1889 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-12 -DNS3_CLANG_TIMETRACE=ON"
1891 except DockerException
as e:
1892 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1895 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1896 if os.path.exists(time_trace_report_path):
1897 os.remove(time_trace_report_path)
1901 container.execute(
"./ns3 build timeTraceReport")
1902 except DockerException
as e:
1903 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1906 self.assertTrue(os.path.exists(time_trace_report_path))
1910 container.execute(
"apt-get install -y g++")
1911 container.execute(
"apt-get remove -y clang-12")
1915 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1918 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1920 except DockerException
as e:
1921 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1925 Check if NS3_NINJA_TRACE feature is working
1926 Ninja's .ninja_log conversion to about://tracing
1927 json format conversion with Ninjatracing
1933 container.execute(
"apt-get update")
1934 container.execute(
"apt-get remove -y g++")
1935 container.execute(
"apt-get install -y python3 cmake g++-10 clang-11")
1940 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11"
1942 except DockerException
as e:
1943 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1948 container.execute(
"apt-get install -y ninja-build")
1952 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11"
1954 except DockerException
as e:
1955 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1957 container.execute(
"apt-get install -y git")
1961 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11"
1963 except DockerException
as e:
1964 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1967 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1968 if os.path.exists(ninja_trace_path):
1969 os.remove(ninja_trace_path)
1972 container.execute(
"./ns3 build core")
1976 container.execute(
"./ns3 build ninjaTrace")
1977 except DockerException
as e:
1978 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1981 self.assertTrue(os.path.exists(ninja_trace_path))
1982 trace_size = os.stat(ninja_trace_path).st_size
1983 os.remove(ninja_trace_path)
1990 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-11 -DNS3_CLANG_TIMETRACE=ON"
1992 except DockerException
as e:
1993 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
1996 container.execute(
"./ns3 build core")
2000 container.execute(
"./ns3 build ninjaTrace")
2001 except DockerException
as e:
2002 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
2004 self.assertTrue(os.path.exists(ninja_trace_path))
2005 timetrace_size = os.stat(ninja_trace_path).st_size
2006 os.remove(ninja_trace_path)
2009 self.assertGreater(timetrace_size, trace_size)
2013 Check if precompiled headers are being enabled correctly.
2023 container.execute(
"apt-get update")
2024 container.execute(
"apt-get install -y python3 cmake ccache g++")
2026 container.execute(
"./ns3 configure")
2027 except DockerException
as e:
2028 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2032 Check for regressions in test object build.
2035 return_code, stdout, stderr =
run_ns3(
"configure")
2036 self.assertEqual(return_code, 0)
2038 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2039 self.assertFalse(os.path.exists(test_module_cache))
2041 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2042 self.assertEqual(return_code, 0)
2043 self.assertTrue(os.path.exists(test_module_cache))
2047 Check for regressions in a bare ns-3 configuration.
2054 container.execute(
"apt-get update")
2055 container.execute(
"apt-get install -y python3 cmake g++")
2059 stdout = container.execute(
"./ns3 configure -d release")
2060 except DockerException
as e:
2062 self.
config_ok(return_code, stdout, stdout)
2069 Tests ns3 regarding building the project
2074 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2083 Try building the core library
2086 return_code, stdout, stderr =
run_ns3(
"build core")
2087 self.assertEqual(return_code, 0)
2088 self.assertIn(
"Built target core", stdout)
2092 Try building core-test library without tests enabled
2096 return_code, stdout, stderr =
run_ns3(
"build core-test")
2097 self.assertEqual(return_code, 1)
2098 self.assertIn(
"Target to build does not exist: core-test", stdout)
2102 Try building the project:
2105 return_code, stdout, stderr =
run_ns3(
"build")
2106 self.assertEqual(return_code, 0)
2107 self.assertIn(
"Built target", stdout)
2109 self.assertTrue(os.path.exists(program), program)
2110 self.assertIn(cmake_build_project_command, stdout)
2114 Try hiding task lines
2117 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2118 self.assertEqual(return_code, 0)
2119 self.assertIn(cmake_build_project_command, stdout)
2123 Try removing an essential file to break the build
2127 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2128 attribute_cc_bak_path = attribute_cc_path +
".bak"
2129 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2132 return_code, stdout, stderr =
run_ns3(
"build")
2133 self.assertNotEqual(return_code, 0)
2136 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2139 return_code, stdout, stderr =
run_ns3(
"build")
2140 self.assertEqual(return_code, 0)
2144 Test if changing the version file affects the library names
2150 version_file = os.sep.join([ns3_path,
"VERSION"])
2151 with open(version_file,
"w", encoding=
"utf-8")
as f:
2155 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2156 self.
config_ok(return_code, stdout, stderr)
2159 return_code, stdout, stderr =
run_ns3(
"build")
2160 self.assertEqual(return_code, 0)
2161 self.assertIn(
"Built target", stdout)
2167 for program
in new_programs:
2168 self.assertTrue(os.path.exists(program))
2175 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2176 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2177 for library
in new_libraries:
2178 self.assertNotIn(
"libns3-dev", library)
2179 self.assertIn(
"libns3-00", library)
2180 self.assertTrue(os.path.exists(library))
2183 with open(version_file,
"w", encoding=
"utf-8")
as f:
2188 Try setting a different output directory and if everything is
2189 in the right place and still working correctly
2194 return_code, stdout, stderr =
run_ns3(
"build")
2195 self.assertEqual(return_code, 0)
2210 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2211 relative_path = os.sep.join([
"build",
"release"])
2212 for different_out_dir
in [absolute_path, relative_path]:
2213 return_code, stdout, stderr =
run_ns3(
2214 'configure -G "{generator}" --out=%s' % different_out_dir
2216 self.
config_ok(return_code, stdout, stderr)
2218 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2227 for program
in new_programs:
2228 self.assertTrue(os.path.exists(program))
2232 new_libraries = list(set(libraries).difference(set(self.
ns3_libraries)))
2233 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
2234 for library
in new_libraries:
2235 self.assertTrue(os.path.exists(library))
2238 shutil.rmtree(absolute_path)
2241 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2242 self.
config_ok(return_code, stdout, stderr)
2244 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2253 for program
in new_programs:
2254 self.assertTrue(os.path.exists(program))
2259 for library
in libraries:
2260 self.assertTrue(os.path.exists(library))
2264 Tries setting a ns3 version, then installing it.
2265 After that, tries searching for ns-3 with CMake's find_package(ns3).
2266 Finally, tries using core library in a 3rd-party project
2271 for library
in libraries:
2275 version_file = os.sep.join([ns3_path,
"VERSION"])
2276 with open(version_file,
"w", encoding=
"utf-8")
as f:
2280 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2281 return_code, stdout, stderr =
run_ns3(
2282 'configure -G "{generator}" --prefix=%s' % install_prefix
2284 self.
config_ok(return_code, stdout, stderr)
2295 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2296 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2300 installed_libraries_list =
";".join(installed_libraries)
2301 for library
in libraries:
2302 library_name = os.path.basename(library)
2303 self.assertIn(library_name, installed_libraries_list)
2307 missing_headers = list(
2308 set([os.path.basename(x)
for x
in headers])
2309 - (set([os.path.basename(x)
for x
in installed_headers]))
2311 self.assertEqual(len(missing_headers), 0)
2314 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2315 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2318 #include <ns3/core-module.h>
2319 using namespace ns3;
2322 Simulator::Stop (Seconds (1.0));
2324 Simulator::Destroy ();
2333 for version
in [
"",
"3.01",
"3.00"]:
2334 ns3_import_methods = []
2337 cmake_find_package_import =
"""
2338 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2339 find_package(ns3 {version} COMPONENTS core)
2340 target_link_libraries(test PRIVATE ns3::core)
2342 lib=(
"lib64" if lib64
else "lib"), version=version
2344 ns3_import_methods.append(cmake_find_package_import)
2347 pkgconfig_import =
"""
2348 list(APPEND CMAKE_PREFIX_PATH ./)
2349 include(FindPkgConfig)
2350 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2351 target_link_libraries(test PUBLIC PkgConfig::ns3)
2353 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2355 if shutil.which(
"pkg-config"):
2356 ns3_import_methods.append(pkgconfig_import)
2359 for import_method
in ns3_import_methods:
2360 test_cmake_project = (
2362 cmake_minimum_required(VERSION 3.12..3.12)
2363 project(ns3_consumer CXX)
2364 set(CMAKE_CXX_STANDARD 20)
2365 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2366 add_executable(test main.cpp)
2371 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2372 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2373 f.write(test_cmake_project)
2376 cmake = shutil.which(
"cmake")
2379 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2380 generator=platform_makefiles
2385 if version ==
"3.00":
2386 self.assertEqual(return_code, 1)
2387 if import_method == cmake_find_package_import:
2389 'Could not find a configuration file for package "ns3" that is compatible',
2390 stderr.replace(
"\n",
""),
2392 elif import_method == pkgconfig_import:
2393 self.assertIn(
"not found", stderr.replace(
"\n",
""))
2395 raise Exception(
"Unknown import type")
2397 self.assertEqual(return_code, 0)
2398 self.assertIn(
"Build files", stdout)
2401 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2403 if version ==
"3.00":
2404 self.assertEqual(return_code, 2, msg=stdout + stderr)
2405 self.assertGreater(len(stderr), 0)
2407 self.assertEqual(return_code, 0)
2408 self.assertIn(
"Built target", stdout)
2412 test_program = os.path.join(install_prefix,
"test.exe")
2413 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2415 "PATH": env_sep.join(
2416 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2420 test_program =
"./test"
2423 test_program,
"", cwd=install_prefix, env=env
2425 self.assertEqual(return_code, 0)
2428 return_code, stdout, stderr =
run_ns3(
"uninstall")
2429 self.assertIn(
"Built target uninstall", stdout)
2432 os.remove(version_file)
2433 with open(version_file,
"w", encoding=
"utf-8")
as f:
2438 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2443 "scratch/scratch-simulator":
"scratch-simulator",
2444 "scratch/scratch-simulator.cc":
"scratch-simulator",
2445 "scratch-simulator":
"scratch-simulator",
2446 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2447 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2448 "scratch-subdir":
"subdir_scratch-subdir",
2450 for target_to_run, target_cmake
in targets.items():
2452 build_line =
"target scratch_%s" % target_cmake
2453 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2454 self.assertEqual(return_code, 0)
2455 self.assertIn(build_line, stdout)
2458 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2459 self.assertEqual(return_code, 0)
2460 self.assertIn(build_line, stdout)
2461 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2462 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2466 Test if ns3 can alert correctly in case a shortcut collision happens
2471 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2472 self.assertEqual(return_code, 0)
2475 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2478 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2479 self.assertEqual(return_code, 0)
2482 return_code, stdout, stderr =
run_ns3(
"build second")
2483 self.assertEqual(return_code, 1)
2485 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2486 stdout.replace(os.sep,
"/"),
2490 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2491 self.assertEqual(return_code, 0)
2495 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2496 self.assertEqual(return_code, 0)
2500 return_code, stdout, stderr =
run_ns3(
"run second")
2501 self.assertEqual(return_code, 1)
2503 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2504 stdout.replace(os.sep,
"/"),
2508 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2509 self.assertEqual(return_code, 0)
2512 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2513 self.assertEqual(return_code, 0)
2516 os.remove(
"./scratch/second.cc")
2520 Test if we can build a static ns-3 library and link it to static programs
2523 if (
not win32)
and (arch ==
"aarch64"):
2524 if platform.libc_ver()[0] ==
"glibc":
2525 from packaging.version
import Version
2527 if Version(platform.libc_ver()[1]) < Version(
"2.37"):
2529 "Static linking on ARM64 requires glibc 2.37 where fPIC was enabled (fpic is limited in number of GOT entries)"
2533 return_code, stdout, stderr =
run_ns3(
2534 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2540 self.assertEqual(return_code, 1)
2541 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2544 self.assertEqual(return_code, 0)
2547 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2548 self.assertEqual(return_code, 0)
2549 self.assertIn(
"Built target", stdout)
2555 Test if we can use python bindings
2560 except ModuleNotFoundError:
2561 self.skipTest(
"Cppyy was not found")
2564 return_code, stdout, stderr =
run_ns3(
2565 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2569 self.assertEqual(return_code, 0)
2572 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2573 self.assertEqual(return_code, 0)
2576 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2577 self.assertEqual(return_code, 0)
2581 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2583 self.assertEqual(return_code, 0)
2587 Test if we had regressions with brite, click and openflow modules
2588 that depend on homonymous libraries
2591 if shutil.which(
"git")
is None:
2592 self.skipTest(
"Missing git")
2595 self.skipTest(
"Optional components are not supported on Windows")
2598 return_code, stdout, stderr =
run_ns3(
"configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON")
2599 self.assertEqual(return_code, 0)
2603 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2604 self.assertEqual(return_code, 0)
2608 Test if we can link contrib modules to src modules
2611 if shutil.which(
"git")
is None:
2612 self.skipTest(
"Missing git")
2614 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2615 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2617 if os.path.exists(destination_contrib):
2618 shutil.rmtree(destination_contrib)
2619 if os.path.exists(destination_src):
2620 shutil.rmtree(destination_src)
2624 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2625 destination_contrib,
2628 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2633 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2634 self.assertEqual(return_code, 0)
2637 return_code, stdout, stderr =
run_ns3(
"run source-example")
2638 self.assertEqual(return_code, 0)
2641 shutil.rmtree(destination_contrib)
2642 shutil.rmtree(destination_src)
2647 Tests ns3 usage in more realistic scenarios
2652 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2653 Here examples, tests and documentation are also enabled.
2660 return_code, stdout, stderr =
run_ns3(
2661 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2663 self.
config_ok(return_code, stdout, stderr)
2666 self.assertTrue(os.path.exists(ns3_lock_filename))
2672 self.assertTrue(os.path.exists(ns3_lock_filename))
2679 Try to build the project
2682 return_code, stdout, stderr =
run_ns3(
"build")
2683 self.assertEqual(return_code, 0)
2684 self.assertIn(
"Built target", stdout)
2686 self.assertTrue(os.path.exists(program))
2689 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2690 self.assertIn(cmake_build_project_command, stdout)
2694 Try to build and run test-runner
2697 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2698 self.assertEqual(return_code, 0)
2699 self.assertIn(
"Built target test-runner", stdout)
2704 Try to build and run a library
2707 return_code, stdout, stderr =
run_ns3(
"run core")
2708 self.assertEqual(return_code, 1)
2709 self.assertIn(
"Couldn't find the specified program: core", stderr)
2713 Try to build and run an unknown target
2716 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2717 self.assertEqual(return_code, 1)
2718 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2722 Try to run test-runner without building
2725 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2726 self.assertEqual(return_code, 0)
2728 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2729 self.assertEqual(return_code, 0)
2730 self.assertNotIn(
"Built target test-runner", stdout)
2735 Test ns3 fails to run a library
2738 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2739 self.assertEqual(return_code, 1)
2740 self.assertIn(
"Couldn't find the specified program: core", stderr)
2744 Test ns3 fails to run an unknown program
2747 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2748 self.assertEqual(return_code, 1)
2749 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2753 Test if scratch simulator is executed through gdb and lldb
2756 if shutil.which(
"gdb")
is None:
2757 self.skipTest(
"Missing gdb")
2759 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2760 self.assertEqual(return_code, 0)
2762 return_code, stdout, stderr =
run_ns3(
2763 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2765 self.assertEqual(return_code, 0)
2766 self.assertIn(
"scratch-simulator", stdout)
2768 self.assertIn(
"GNU gdb", stdout)
2770 self.assertIn(
"No debugging symbols found", stdout)
2774 Test if scratch simulator is executed through valgrind
2777 if shutil.which(
"valgrind")
is None:
2778 self.skipTest(
"Missing valgrind")
2780 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2781 self.assertEqual(return_code, 0)
2783 return_code, stdout, stderr =
run_ns3(
2784 "run scratch-simulator --valgrind --verbose --no-build"
2786 self.assertEqual(return_code, 0)
2787 self.assertIn(
"scratch-simulator", stderr)
2788 self.assertIn(
"Memcheck", stderr)
2792 Test the doxygen target that does trigger a full build
2795 if shutil.which(
"doxygen")
is None:
2796 self.skipTest(
"Missing doxygen")
2798 if shutil.which(
"bash")
is None:
2799 self.skipTest(
"Missing bash")
2801 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2803 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2804 for filename
in doxygen_files:
2805 file_path = os.sep.join([doc_folder, filename])
2806 if os.path.exists(file_path):
2807 os.remove(file_path)
2814 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2815 self.assertEqual(return_code, 0)
2817 self.assertIn(
"Built target doxygen", stdout)
2821 Test the doxygen target that doesn't trigger a full build
2824 if shutil.which(
"doxygen")
is None:
2825 self.skipTest(
"Missing doxygen")
2833 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2834 self.assertEqual(return_code, 0)
2836 self.assertIn(
"Built target doxygen-no-build", stdout)
2840 Test every individual target for Sphinx-based documentation
2843 if shutil.which(
"sphinx-build")
is None:
2844 self.skipTest(
"Missing sphinx")
2846 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2849 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2851 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2852 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2853 if os.path.exists(doc_build_folder):
2854 shutil.rmtree(doc_build_folder)
2855 if os.path.exists(doc_temp_folder):
2856 shutil.rmtree(doc_temp_folder)
2859 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2860 self.assertEqual(return_code, 0, target)
2862 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2865 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2866 self.assertTrue(os.path.exists(doc_build_folder))
2869 for build_type
in [
"latex",
"html",
"singlehtml"]:
2870 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2874 Test the documentation target that builds
2875 both doxygen and sphinx based documentation
2878 if shutil.which(
"doxygen")
is None:
2879 self.skipTest(
"Missing doxygen")
2880 if shutil.which(
"sphinx-build")
is None:
2881 self.skipTest(
"Missing sphinx")
2883 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2892 for target
in [
"manual",
"models",
"tutorial"]:
2893 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2894 if os.path.exists(doc_build_folder):
2895 shutil.rmtree(doc_build_folder)
2897 return_code, stdout, stderr =
run_ns3(
"docs all")
2898 self.assertEqual(return_code, 0)
2900 self.assertIn(
"Built target sphinx", stdout)
2902 self.assertIn(
"Built target doxygen", stdout)
2906 Try to set ownership of scratch-simulator from current user to root,
2907 and change execution permissions
2912 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2915 if sudo_password
is None:
2916 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2919 self.assertFalse(enable_sudo
is True)
2922 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2923 self.assertEqual(return_code, 0)
2924 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2926 scratch_simulator_path = list(
2929 prev_fstat = os.stat(scratch_simulator_path)
2932 return_code, stdout, stderr =
run_ns3(
2933 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2935 self.assertEqual(return_code, 0)
2936 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2938 fstat = os.stat(scratch_simulator_path)
2944 likely_fuse_mount = (
2945 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2946 )
and prev_fstat.st_uid == 0
2948 if win32
or likely_fuse_mount:
2949 self.skipTest(
"Windows or likely a FUSE mount")
2952 self.assertEqual(fstat.st_uid, 0)
2954 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2958 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2959 self.assertEqual(return_code, 0)
2963 self.assertTrue(enable_sudo)
2967 if os.path.exists(executable):
2968 os.remove(executable)
2971 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2972 self.assertEqual(return_code, 0)
2975 self.assertIn(
"chown root", stdout)
2976 self.assertIn(
"chmod u+s", stdout)
2978 self.assertIn(os.path.basename(executable), stdout)
2981 fstat = os.stat(scratch_simulator_path)
2982 self.assertEqual(fstat.st_uid, 0)
2984 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2989 Check if command template is working
2994 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
2995 self.assertEqual(return_code0, 2)
2996 self.assertIn(
"argument --command-template: expected one argument", stderr0)
2998 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
2999 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
3000 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
3001 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
3002 for stderr
in [stderr1, stderr2, stderr3]:
3003 self.assertIn(
"not all arguments converted during string formatting", stderr)
3006 return_code4, stdout4, _ =
run_ns3(
3007 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
3009 return_code5, stdout5, _ =
run_ns3(
3010 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
3012 self.assertEqual((return_code4, return_code5), (0, 0))
3014 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3015 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3019 Check if all flavors of different argument passing to
3020 executable targets are working
3025 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3026 return_code1, stdout1, stderr1 =
run_ns3(
3027 'run sample-simulator --command-template="%s --help" --verbose'
3029 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3031 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3032 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3033 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3034 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3037 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3038 return_code1, stdout1, stderr1 =
run_ns3(
3039 'run sample-simulator --command-template="%s --help" --no-build'
3041 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3042 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3043 self.assertEqual(stdout0, stdout1)
3044 self.assertEqual(stdout1, stdout2)
3045 self.assertEqual(stderr0, stderr1)
3046 self.assertEqual(stderr1, stderr2)
3049 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3050 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3051 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3053 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3054 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3055 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3056 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3059 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3060 return_code, stdout, stderr =
run_ns3(cmd)
3061 self.assertEqual(return_code, 0)
3067 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3072 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3073 cmd1 =
"run sample-simulator --PrintTypeIds"
3075 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3076 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3077 self.assertEqual((return_code0, return_code1), (1, 1))
3078 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3079 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3083 Test if scratch simulator is executed through lldb
3086 if shutil.which(
"lldb")
is None:
3087 self.skipTest(
"Missing lldb")
3089 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3090 self.assertEqual(return_code, 0)
3092 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3093 self.assertEqual(return_code, 0)
3094 self.assertIn(
"scratch-simulator", stdout)
3095 self.assertIn(
"(lldb) target create", stdout)
3099 Test if CPM and Vcpkg package managers are working properly
3103 return_code, stdout, stderr =
run_ns3(
"clean")
3104 self.assertEqual(return_code, 0)
3107 if os.path.exists(
"vcpkg"):
3108 shutil.rmtree(
"vcpkg")
3111 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3113 if os.path.exists(destination_src):
3114 shutil.rmtree(destination_src)
3118 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3124 container.execute(
"apt-get update")
3125 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3130 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3131 self.skipTest(
"Armadillo is already installed")
3132 except DockerException
as e:
3136 return_code, stdout, stderr =
run_ns3(
"clean")
3137 self.assertEqual(return_code, 0)
3140 container.execute(
"apt-get install -y git")
3145 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3147 except DockerException
as e:
3152 container.execute(
"./ns3 build test-package-managers")
3153 except DockerException
as e:
3157 return_code, stdout, stderr =
run_ns3(
"clean")
3158 self.assertEqual(return_code, 0)
3160 if arch !=
"aarch64":
3162 container.execute(
"apt-get install -y zip unzip tar curl")
3165 container.execute(
"apt-get install -y pkg-config gfortran")
3169 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3170 except DockerException
as e:
3175 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3176 except DockerException
as e:
3181 container.execute(
"./ns3 build test-package-managers")
3182 except DockerException
as e:
3186 if os.path.exists(destination_src):
3187 shutil.rmtree(destination_src)
3192 ns-3 tests to control the quality of the repository over time,
3193 by checking the state of URLs listed and more
3198 Test if all urls in source files are alive
3207 self.skipTest(
"Django URL validators are not available")
3214 urllib3.disable_warnings()
3217 self.skipTest(
"Requests library is not available")
3219 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3222 whitelisted_urls = {
3223 "https://gitlab.com/your-user-name/ns-3-dev",
3224 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3225 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3226 "https://www.nsnam.org/releases/ns-3-x",
3227 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3228 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3229 "https://ns-buildmaster.ee.washington.edu:8010/",
3231 "https://cmake.org/cmake/help/latest/manual/cmake-",
3232 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3234 "http://www.lysator.liu.se/~alla/dia/",
3236 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3237 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3238 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3239 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3241 "http://www.research.att.com/info/kpv/",
3242 "http://www.research.att.com/~gsf/",
3243 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3244 "http://scan5.coverity.com/cgi-bin/upload.py",
3246 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3247 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3251 files_and_urls = set()
3253 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3254 for root, dirs, files
in os.walk(topdir):
3256 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3259 filepath = os.path.join(root, file)
3262 if not os.path.isfile(filepath):
3266 if file.endswith(
".svg"):
3270 with open(filepath,
"r", encoding=
"utf-8")
as f:
3271 matches = regex.findall(f.read())
3277 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3279 except UnicodeDecodeError:
3280 skipped_files.append(filepath)
3284 for url
in set(urls) - unique_urls - whitelisted_urls:
3285 unique_urls.add(url)
3286 files_and_urls.add((filepath, url))
3289 from django.core.exceptions
import ValidationError
3290 from django.core.validators
import URLValidator
3292 validate_url = URLValidator()
3296 "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"
3300 def test_file_url(args):
3301 test_filepath, test_url = args
3302 dead_link_msg =
None
3306 validate_url(test_url)
3307 except ValidationError:
3308 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3309 except Exception
as e:
3310 self.assertEqual(
False,
True, msg=e.__str__())
3312 if dead_link_msg
is not None:
3313 return dead_link_msg
3321 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3324 if response.status_code
in [200, 301]:
3325 dead_link_msg =
None
3330 if response.status_code
in [302, 308, 500, 503]:
3331 if response.reason.lower()
in [
3333 "moved temporarily",
3334 "permanent redirect",
3336 "service temporarily unavailable",
3338 dead_link_msg =
None
3342 dead_link_msg =
"%s: URL %s: returned code %d" % (
3345 response.status_code,
3347 except requests.exceptions.InvalidURL:
3348 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3349 except requests.exceptions.SSLError:
3350 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3351 except requests.exceptions.TooManyRedirects:
3352 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3353 except Exception
as e:
3355 error_msg = e.args[0].reason.__str__()
3356 except AttributeError:
3357 error_msg = e.args[0]
3358 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3364 return dead_link_msg
3367 from concurrent.futures
import ThreadPoolExecutor
3369 with ThreadPoolExecutor(max_workers=100)
as executor:
3370 dead_links = list(executor.map(test_file_url, list(files_and_urls)))
3373 dead_links = list(sorted(filter(
lambda x: x
is not None, dead_links)))
3374 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3378 Test if all tests can be executed without hitting major memory bugs
3381 return_code, stdout, stderr =
run_ns3(
3382 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3384 self.assertEqual(return_code, 0)
3386 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3387 self.assertEqual(test_return_code, 0)
3391 Check if images in the docs are above a brightness threshold.
3392 This should prevent screenshots with dark UI themes.
3395 if shutil.which(
"convert")
is None:
3396 self.skipTest(
"Imagemagick was not found")
3398 from pathlib
import Path
3401 image_extensions = [
"png",
"jpg"]
3403 for extension
in image_extensions:
3404 images += list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3405 images += list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3408 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3412 brightness_threshold = 50
3413 for image
in images:
3414 brightness = subprocess.check_output(
3415 imagemagick_get_image_brightness.format(image=image).split()
3417 brightness = float(brightness.decode().strip(
"'\""))
3420 brightness_threshold,
3421 "Image darker than threshold (%d < %d): %s"
3422 % (brightness, brightness_threshold, image),
3427 Check if one of the log statements of examples/tests contains/exposes a bug.
3431 return_code, stdout, stderr =
run_ns3(
3432 'configure -G "{generator}" -d release --enable-examples --enable-tests --enable-sanitizers'
3434 self.assertEqual(return_code, 0)
3438 "test.py",
"", python=
True, env={
"TEST_LOGS":
"1"}
3440 self.assertEqual(return_code, 0)
3449 test_completeness = {
3451 NS3UnusedSourcesTestCase,
3455 NS3CommonSettingsTestCase,
3456 NS3ConfigureBuildProfileTestCase,
3457 NS3ConfigureTestCase,
3458 NS3BuildBaseTestCase,
3459 NS3ExpectedUseTestCase,
3462 NS3UnusedSourcesTestCase,
3464 NS3CommonSettingsTestCase,
3465 NS3ConfigureBuildProfileTestCase,
3466 NS3ConfigureTestCase,
3467 NS3BuildBaseTestCase,
3468 NS3ExpectedUseTestCase,
3469 NS3QualityControlTestCase,
3472 NS3DependenciesTestCase,
3478 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3479 parser.add_argument(
3480 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3482 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3483 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3484 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3485 args = parser.parse_args(sys.argv[1:])
3487 loader = unittest.TestLoader()
3488 suite = unittest.TestSuite()
3491 for testCase
in test_completeness[args.completeness]:
3492 suite.addTests(loader.loadTestsFromTestCase(testCase))
3497 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3499 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3500 tests_to_remove = set(tests) - set(tests_to_run)
3501 for test_to_remove
in tests_to_remove:
3502 suite._tests.remove(tests[test_to_remove])
3505 if args.resume_from_test_name:
3507 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3508 keys = list(tests.keys())
3510 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3511 suite._tests.remove(tests[keys[0]])
3515 ns3rc_script_bak = ns3rc_script +
".bak"
3516 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3517 shutil.move(ns3rc_script, ns3rc_script_bak)
3520 runner = unittest.TextTestRunner(failfast=
True, verbosity=1
if args.quiet
else 2)
3524 if os.path.exists(ns3rc_script_bak):
3525 shutil.move(ns3rc_script_bak, ns3rc_script)
3528if __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_executables
ns3_executables holds a list of executables in .lock-ns3 # noqa
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...
ns3_modules
ns3_modules holds a list to the modules enabled stored in .lock-ns3 # noqa
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.
ns3_executables
ns3_executables holds a list of executables in .lock-ns3 # noqa
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, by checking the state of URLs listed a...
test_02_MemoryCheckWithSanitizers(self)
Test if all tests can be executed without hitting major memory bugs.
test_03_CheckImageBrightness(self)
Check if images in the docs are above a brightness threshold.
test_04_CheckForBrokenLogs(self)
Check if one of the log statements of examples/tests contains/exposes a bug.
test_01_CheckForDeadLinksInSources(self)
Test if all urls in source files are alive.
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.