21 Test suite for the ns3 wrapper script
31 from functools
import partial
34 ns3_path = os.path.dirname(os.path.abspath(os.sep.join([__file__,
"../../"])))
35 ns3_lock_filename = os.path.join(ns3_path,
".lock-ns3_%s_build" % sys.platform)
36 ns3_script = os.sep.join([ns3_path,
"ns3"])
37 ns3rc_script = os.sep.join([ns3_path,
".ns3rc"])
38 usual_outdir = os.sep.join([ns3_path,
"build"])
39 usual_lib_outdir = os.sep.join([usual_outdir,
"lib"])
45 num_threads =
max(1, os.cpu_count() - 1)
46 cmake_build_project_command =
"cmake --build {cmake_cache} -j".format(
47 ns3_path=ns3_path, cmake_cache=os.path.abspath(os.path.join(ns3_path,
"cmake-cache"))
49 cmake_build_target_command = partial(
50 "cmake --build {cmake_cache} -j {jobs} --target {target}".format,
52 cmake_cache=os.path.abspath(os.path.join(ns3_path,
"cmake-cache")),
54 win32 = sys.platform ==
"win32"
55 platform_makefiles =
"MinGW Makefiles" if win32
else "Unix Makefiles"
56 ext =
".exe" if win32
else ""
59 def run_ns3(args, env=None, generator=platform_makefiles):
61 Runs the ns3 wrapper script with arguments
62 @param args: string containing arguments that will get split before calling ns3
63 @param env: environment variables dictionary
64 @param generator: CMake generator
65 @return tuple containing (error code, stdout and stderr)
68 possible_leftovers = [
"contrib/borked",
"contrib/calibre"]
69 for leftover
in possible_leftovers:
70 if os.path.exists(leftover):
71 shutil.rmtree(leftover, ignore_errors=
True)
73 args = args.format(generator=generator)
78 return run_program(ns3_script, args, python=
True, env=env)
82 def run_program(program, args, python=False, cwd=ns3_path, env=None):
84 Runs a program with the given arguments and returns a tuple containing (error code, stdout and stderr)
85 @param program: program to execute (or python script)
86 @param args: string containing arguments that will get split before calling the program
87 @param python: flag indicating whether the program is a python script
88 @param cwd: the working directory used that will be the root folder for the execution
89 @param env: environment variables dictionary
90 @return tuple containing (error code, stdout and stderr)
93 raise Exception(
"args should be a string")
97 arguments = [sys.executable, program]
102 arguments.extend(re.findall(
'(?:".*?"|\S)+', args))
104 for i
in range(len(arguments)):
105 arguments[i] = arguments[i].replace(
'"',
"")
108 current_env = os.environ.copy()
112 current_env.update(env)
115 ret = subprocess.run(
117 stdin=subprocess.DEVNULL,
118 stdout=subprocess.PIPE,
119 stderr=subprocess.PIPE,
126 ret.stdout.decode(sys.stdout.encoding),
127 ret.stderr.decode(sys.stderr.encoding),
133 Extracts the programs list from .lock-ns3
134 @return list of programs.
137 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
138 exec(f.read(), globals(), values)
140 programs_list = values[
"ns3_runnable_programs"]
144 programs_list =
list(map(
lambda x: x + ext, programs_list))
150 Gets a list of built libraries
151 @param lib_outdir: path containing libraries
152 @return list of built libraries.
154 libraries = glob.glob(lib_outdir +
"/*", recursive=
True)
155 return list(filter(
lambda x:
"scratch-nested-subdir-lib" not in x, libraries))
160 Gets a list of header files
161 @param outdir: path containing headers
162 @return list of headers.
164 return glob.glob(outdir +
"/**/*.h", recursive=
True)
169 Read interesting entries from the .lock-ns3 file
170 @param entry: entry to read from .lock-ns3
171 @return value of the requested entry.
174 with open(ns3_lock_filename, encoding=
"utf-8")
as f:
175 exec(f.read(), globals(), values)
176 return values.get(entry,
None)
181 Check if tests are enabled in the .lock-ns3
189 Check if tests are enabled in the .lock-ns3
190 @return list of enabled modules (prefixed with 'ns3-').
197 Python-on-whales wrapper for Docker-based ns-3 tests
200 def __init__(self, currentTestCase: unittest.TestCase, containerName: str =
"ubuntu:latest"):
202 Create and start container with containerName in the current ns-3 directory
203 @param self: the current DockerContainerManager instance
204 @param currentTestCase: the test case instance creating the DockerContainerManager
205 @param containerName: name of the container image to be used
207 global DockerException
209 from python_on_whales
import docker
210 from python_on_whales.exceptions
import DockerException
211 except ModuleNotFoundError:
213 DockerException =
None
214 currentTestCase.skipTest(
"python-on-whales was not found")
217 with open(os.path.expanduser(
"~/.bashrc"),
"r", encoding=
"utf-8")
as f:
218 docker_settings = re.findall(
"(DOCKER_.*=.*)", f.read())
219 for setting
in docker_settings:
220 key, value = setting.split(
"=")
221 os.environ[key] = value
222 del docker_settings, setting, key, value
231 volumes=[(ns3_path,
"/ns-3-dev")],
235 def split_exec(docker_container, cmd):
236 return docker_container._execute(cmd.split(), workdir=
"/ns-3-dev")
243 Return the managed container when entiring the block "with DockerContainerManager() as container"
244 @param self: the current DockerContainerManager instance
245 @return container managed by DockerContainerManager.
251 Clean up the managed container at the end of the block "with DockerContainerManager() as container"
252 @param self: the current DockerContainerManager instance
253 @param exc_type: unused parameter
254 @param exc_val: unused parameter
255 @param exc_tb: unused parameter
264 ns-3 tests related to checking if source files were left behind, not being used by CMake
268 directory_and_files = {}
272 Scan all C++ source files and add them to a list based on their path
275 for root, dirs, files
in os.walk(ns3_path):
276 if "gitlab-ci-local" in root:
279 if name.endswith(
".cc"):
280 path = os.path.join(root, name)
281 directory = os.path.dirname(path)
288 Test if all example source files are being used in their respective CMakeLists.txt
291 unused_sources = set()
294 if os.sep +
"examples" not in example_directory:
299 os.path.join(example_directory,
"CMakeLists.txt"),
"r", encoding=
"utf-8"
301 cmake_contents = f.read()
306 if os.path.basename(file).replace(
".cc",
"")
not in cmake_contents:
307 unused_sources.add(file)
309 self.assertListEqual([],
list(unused_sources))
313 Test if all module source files are being used in their respective CMakeLists.txt
316 unused_sources = set()
319 is_not_module =
not (
"src" in directory
or "contrib" in directory)
320 is_example = os.sep +
"examples" in directory
321 is_bindings = os.sep +
"bindings" in directory
323 if is_not_module
or is_bindings
or is_example:
328 cmake_path = os.path.join(directory,
"CMakeLists.txt")
329 while not os.path.exists(cmake_path):
330 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
331 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
334 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
335 cmake_contents = f.read()
339 if os.path.basename(file)
not in cmake_contents:
340 unused_sources.add(file)
344 "win32-system-wall-clock-ms.cc",
346 for exception
in exceptions:
347 for unused_source
in unused_sources:
348 if os.path.basename(unused_source) == exception:
349 unused_sources.remove(unused_source)
352 self.assertListEqual([],
list(unused_sources))
356 Test if all utils source files are being used in their respective CMakeLists.txt
359 unused_sources = set()
362 is_module =
"src" in directory
or "contrib" in directory
363 if os.sep +
"utils" not in directory
or is_module:
368 cmake_path = os.path.join(directory,
"CMakeLists.txt")
369 while not os.path.exists(cmake_path):
370 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
371 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
374 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
375 cmake_contents = f.read()
379 if os.path.basename(file)
not in cmake_contents:
380 unused_sources.add(file)
382 self.assertListEqual([],
list(unused_sources))
387 ns-3 tests related to dependencies
392 Checks if headers from different modules (src/A, contrib/B) that are included by
393 the current module (src/C) source files correspond to the list of linked modules
395 LIBRARIES_TO_LINK A (missing B)
399 headers_to_modules = {}
400 module_paths = glob.glob(ns3_path +
"/src/*/") + glob.glob(ns3_path +
"/contrib/*/")
402 for path
in module_paths:
404 cmake_path = os.path.join(path,
"CMakeLists.txt")
405 with open(cmake_path,
"r", encoding=
"utf-8")
as f:
406 cmake_contents = f.readlines()
408 module_name = os.path.relpath(path, ns3_path)
409 module_name_nodir = module_name.replace(
"src/",
"").replace(
"contrib/",
"")
410 modules[module_name_nodir] = {
414 "included_headers": set(),
415 "included_libraries": set(),
419 for line
in cmake_contents:
420 source_file_path = re.findall(
r"\b(?:[^\s]+\.[ch]{1,2})\b", line.strip())
421 if not source_file_path:
423 source_file_path = source_file_path[0]
424 base_name = os.path.basename(source_file_path)
425 if not os.path.exists(os.path.join(path, source_file_path)):
428 if ".h" in source_file_path:
430 modules[module_name_nodir][
"headers"].add(base_name)
431 modules[module_name_nodir][
"sources"].add(base_name)
434 headers_to_modules[base_name] = module_name_nodir
436 if ".cc" in source_file_path:
438 modules[module_name_nodir][
"sources"].add(base_name)
440 if ".cc" in source_file_path
or ".h" in source_file_path:
442 source_file = os.path.join(ns3_path, module_name, source_file_path)
443 with open(source_file,
"r", encoding=
"utf-8")
as f:
444 source_contents = f.read()
445 modules[module_name_nodir][
"included_headers"].update(
447 lambda x: x.replace(
"ns3/",
""),
448 re.findall(
'#include.*["|<](.*)["|>]', source_contents),
454 modules[module_name_nodir][
"libraries"].update(
455 re.findall(
"\${lib(.*?)}",
"".join(cmake_contents))
457 modules[module_name_nodir][
"libraries"] =
list(
460 not in [
"raries_to_link", module_name_nodir, module_name_nodir +
"-obj"],
461 modules[module_name_nodir][
"libraries"],
466 all_project_headers = set(headers_to_modules.keys())
469 print(file=sys.stderr)
470 for module
in sorted(modules):
471 external_headers = modules[module][
"included_headers"].difference(all_project_headers)
472 project_headers_included = modules[module][
"included_headers"].difference(
475 modules[module][
"included_libraries"] = set(
476 [headers_to_modules[x]
for x
in project_headers_included]
477 ).difference({module})
479 diff = modules[module][
"included_libraries"].difference(modules[module][
"libraries"])
482 def recursive_check_dependencies(checked_module):
484 for module_to_link
in modules[checked_module][
"included_libraries"]:
485 modules[checked_module][
"included_libraries"] = set(
486 modules[checked_module][
"included_libraries"]
487 ) - set(modules[module_to_link][
"included_libraries"])
489 for module_to_link
in modules[checked_module][
"included_libraries"]:
490 recursive_check_dependencies(module_to_link)
493 def is_implicitly_linked(searched_module, current_module):
494 if len(modules[current_module][
"included_libraries"]) == 0:
496 if searched_module
in modules[current_module][
"included_libraries"]:
498 for module
in modules[current_module][
"included_libraries"]:
499 if is_implicitly_linked(searched_module, module):
503 from itertools
import combinations
505 implicitly_linked = set()
506 for dep1, dep2
in combinations(modules[checked_module][
"included_libraries"], 2):
507 if is_implicitly_linked(dep1, dep2):
508 implicitly_linked.add(dep1)
509 if is_implicitly_linked(dep2, dep1):
510 implicitly_linked.add(dep2)
512 modules[checked_module][
"included_libraries"] = (
513 set(modules[checked_module][
"included_libraries"]) - implicitly_linked
516 for module
in modules:
517 recursive_check_dependencies(module)
520 for module
in sorted(modules):
523 minimal_linking_set =
", ".join(modules[module][
"included_libraries"])
524 unnecessarily_linked =
", ".join(
525 set(modules[module][
"libraries"]) - set(modules[module][
"included_libraries"])
527 missing_linked =
", ".join(
528 set(modules[module][
"included_libraries"]) - set(modules[module][
"libraries"])
530 if unnecessarily_linked:
531 print(f
"Module '{module}' unnecessarily linked: {unnecessarily_linked}.")
533 print(f
"Module '{module}' missing linked: {missing_linked}.")
534 if unnecessarily_linked
or missing_linked:
535 print(f
"Module '{module}' minimal linking set: {minimal_linking_set}.")
536 self.assertTrue(
True)
541 ns-3 tests to check if the source code, whitespaces and CMake formatting
542 are according to the coding style
552 Import GitRepo and load the original diff state of the repository before the tests
555 if not NS3StyleTestCase.starting_diff:
556 if shutil.which(
"git")
is None:
557 self.skipTest(
"Git is not available")
563 self.skipTest(
"GitPython is not available")
566 repo = Repo(ns3_path)
567 except git.exc.InvalidGitRepositoryError:
568 self.skipTest(
"ns-3 directory does not contain a .git directory")
570 hcommit = repo.head.commit
571 NS3StyleTestCase.starting_diff = hcommit.diff(
None)
572 NS3StyleTestCase.repo = repo
574 if NS3StyleTestCase.starting_diff
is None:
575 self.skipTest(
"Unmet dependencies")
579 Check if there is any difference between tracked file after
580 applying cmake-format
584 for required_program
in [
"cmake",
"cmake-format"]:
585 if shutil.which(required_program)
is None:
586 self.skipTest(
"%s was not found" % required_program)
589 return_code, stdout, stderr =
run_ns3(
"configure")
590 self.assertEqual(return_code, 0)
593 return_code, stdout, stderr =
run_ns3(
"build cmake-format")
594 self.assertEqual(return_code, 0)
597 return_code, stdout, stderr =
run_ns3(
"clean")
598 self.assertEqual(return_code, 0)
601 new_diff = NS3StyleTestCase.repo.head.commit.diff(
None)
602 self.assertEqual(NS3StyleTestCase.starting_diff, new_diff)
607 ns3 tests related to generic options
612 Clean configuration/build artifacts before common commands
621 Test not passing any arguments to
624 return_code, stdout, stderr =
run_ns3(
"")
625 self.assertEqual(return_code, 1)
626 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
630 Test only passing --quiet argument to ns3
633 return_code, stdout, stderr =
run_ns3(
"--quiet")
634 self.assertEqual(return_code, 1)
635 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
639 Test only passing 'show config' argument to ns3
642 return_code, stdout, stderr =
run_ns3(
"show config")
643 self.assertEqual(return_code, 1)
644 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
648 Test only passing 'show profile' argument to ns3
651 return_code, stdout, stderr =
run_ns3(
"show profile")
652 self.assertEqual(return_code, 1)
653 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
657 Test only passing 'show version' argument to ns3
660 return_code, stdout, stderr =
run_ns3(
"show version")
661 self.assertEqual(return_code, 1)
662 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
667 ns3 tests related to build profiles
672 Clean configuration/build artifacts before testing configuration settings
684 return_code, stdout, stderr =
run_ns3(
685 'configure -G "{generator}" -d debug --enable-verbose'
687 self.assertEqual(return_code, 0)
688 self.assertIn(
"Build profile : debug", stdout)
689 self.assertIn(
"Build files have been written to", stdout)
692 return_code, stdout, stderr =
run_ns3(
"build core")
693 self.assertEqual(return_code, 0)
694 self.assertIn(
"Built target libcore", stdout)
697 self.assertGreater(len(libraries), 0)
698 self.assertIn(
"core-debug", libraries[0])
702 Test the release build
705 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d release')
706 self.assertEqual(return_code, 0)
707 self.assertIn(
"Build profile : release", stdout)
708 self.assertIn(
"Build files have been written to", stdout)
712 Test the optimized build
715 return_code, stdout, stderr =
run_ns3(
716 'configure -G "{generator}" -d optimized --enable-verbose'
718 self.assertEqual(return_code, 0)
719 self.assertIn(
"Build profile : optimized", stdout)
720 self.assertIn(
"Build files have been written to", stdout)
723 return_code, stdout, stderr =
run_ns3(
"build core")
724 self.assertEqual(return_code, 0)
725 self.assertIn(
"Built target libcore", stdout)
728 self.assertGreater(len(libraries), 0)
729 self.assertIn(
"core-optimized", libraries[0])
733 Test a build type with a typo
736 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d Optimized')
737 self.assertEqual(return_code, 2)
738 self.assertIn(
"invalid choice: 'Optimized'", stderr)
742 Test a build type with another typo
745 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" -d OPTIMIZED')
746 self.assertEqual(return_code, 2)
747 self.assertIn(
"invalid choice: 'OPTIMIZED'", stderr)
751 Replace settings set by default (e.g. ASSERT/LOGs enabled in debug builds and disabled in default ones)
754 return_code, _, _ =
run_ns3(
"clean")
755 self.assertEqual(return_code, 0)
757 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run -d debug')
758 self.assertEqual(return_code, 0)
760 "-DCMAKE_BUILD_TYPE=debug -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=ON -DNS3_NATIVE_OPTIMIZATIONS=OFF",
764 return_code, stdout, stderr =
run_ns3(
765 'configure -G "{generator}" --dry-run -d debug --disable-asserts --disable-logs --disable-werror'
767 self.assertEqual(return_code, 0)
769 "-DCMAKE_BUILD_TYPE=debug -DNS3_NATIVE_OPTIMIZATIONS=OFF -DNS3_ASSERT=OFF -DNS3_LOG=OFF -DNS3_WARNINGS_AS_ERRORS=OFF",
773 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --dry-run')
774 self.assertEqual(return_code, 0)
776 "-DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF -DNS3_NATIVE_OPTIMIZATIONS=OFF",
780 return_code, stdout, stderr =
run_ns3(
781 'configure -G "{generator}" --dry-run --enable-asserts --enable-logs --enable-werror'
783 self.assertEqual(return_code, 0)
785 "-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",
792 Generic test case with basic function inherited by more complex tests.
797 Check if configuration for release mode worked normally
798 @param return_code: return code from CMake
799 @param stdout: output from CMake.
800 @param stderr: error from CMake.
803 self.assertEqual(return_code, 0)
804 self.assertIn(
"Build profile : release", stdout)
805 self.assertIn(
"Build files have been written to", stdout)
806 self.assertNotIn(
"uninitialized variable", stderr)
810 Clean configuration/build artifacts before testing configuration and build settings
811 After configuring the build as release,
812 check if configuration worked and check expected output files.
817 if os.path.exists(ns3rc_script):
818 os.remove(ns3rc_script)
822 return_code, stdout, stderr =
run_ns3(
823 'configure -G "{generator}" -d release --enable-verbose'
825 self.
config_okconfig_ok(return_code, stdout, stderr)
828 self.assertTrue(os.path.exists(ns3_lock_filename))
833 self.assertTrue(os.path.exists(ns3_lock_filename))
840 Test ns3 configuration options
845 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
852 Test enabling and disabling examples
855 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
858 self.
config_okconfig_ok(return_code, stdout, stderr)
865 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
868 self.
config_okconfig_ok(return_code, stdout, stderr)
875 Test enabling and disabling tests
879 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-tests')
880 self.
config_okconfig_ok(return_code, stdout, stderr)
883 return_code, stdout, stderr =
run_ns3(
"build core-test")
886 self.assertEqual(return_code, 0)
887 self.assertIn(
"Built target libcore-test", stdout)
890 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-tests')
891 self.
config_okconfig_ok(return_code, stdout, stderr)
894 return_code, stdout, stderr =
run_ns3(
"build core-test")
897 self.assertEqual(return_code, 1)
898 self.assertIn(
"Target to build does not exist: core-test", stdout)
902 Test enabling specific modules
906 return_code, stdout, stderr =
run_ns3(
907 "configure -G \"{generator}\" --enable-modules='network;wifi'"
909 self.
config_okconfig_ok(return_code, stdout, stderr)
915 self.assertIn(
"ns3-network", enabled_modules)
916 self.assertIn(
"ns3-wifi", enabled_modules)
919 return_code, stdout, stderr =
run_ns3(
920 "configure -G \"{generator}\" --enable-modules='core'"
922 self.
config_okconfig_ok(return_code, stdout, stderr)
926 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
927 self.
config_okconfig_ok(return_code, stdout, stderr)
934 Test disabling specific modules
938 return_code, stdout, stderr =
run_ns3(
939 "configure -G \"{generator}\" --disable-modules='lte;wimax'"
941 self.
config_okconfig_ok(return_code, stdout, stderr)
945 self.assertLess(len(enabled_modules), len(self.
ns3_modulesns3_modules))
946 self.assertNotIn(
"ns3-lte", enabled_modules)
947 self.assertNotIn(
"ns3-wimax", enabled_modules)
950 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
951 self.
config_okconfig_ok(return_code, stdout, stderr)
958 Test enabling comma-separated (waf-style) examples
962 return_code, stdout, stderr =
run_ns3(
963 "configure -G \"{generator}\" --enable-modules='network,wifi'"
965 self.
config_okconfig_ok(return_code, stdout, stderr)
970 self.assertIn(
"ns3-network", enabled_modules)
971 self.assertIn(
"ns3-wifi", enabled_modules)
974 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
975 self.
config_okconfig_ok(return_code, stdout, stderr)
982 Test disabling comma-separated (waf-style) examples
986 return_code, stdout, stderr =
run_ns3(
987 "configure -G \"{generator}\" --disable-modules='lte,mpi'"
989 self.
config_okconfig_ok(return_code, stdout, stderr)
993 self.assertLess(len(enabled_modules), len(self.
ns3_modulesns3_modules))
994 self.assertNotIn(
"ns3-lte", enabled_modules)
995 self.assertNotIn(
"ns3-mpi", enabled_modules)
998 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --disable-modules=''")
999 self.
config_okconfig_ok(return_code, stdout, stderr)
1006 Test loading settings from the ns3rc config file
1012 ns3rc_python_template =
"# ! /usr/bin/env python\
1014 # A list of the modules that will be enabled when ns-3 is run.\
1015 # Modules that depend on the listed modules will be enabled also.\
1017 # All modules can be enabled by choosing 'all_modules'.\
1018 modules_enabled = [{modules}]\
1020 # Set this equal to true if you want examples to be run.\
1021 examples_enabled = {examples}\
1023 # Set this equal to true if you want tests to be run.\
1024 tests_enabled = {tests}\
1028 ns3rc_cmake_template =
"set(ns3rc_tests_enabled {tests})\
1029 \nset(ns3rc_examples_enabled {examples})\
1030 \nset(ns3rc_enabled_modules {modules})\
1034 ns3rc_templates = {
"python": ns3rc_python_template,
"cmake": ns3rc_cmake_template}
1036 def __init__(self, type_ns3rc):
1040 def format(self, **args):
1042 if self.
typetype ==
"cmake":
1044 args[
"modules"].replace(
"'",
"").replace(
'"',
"").replace(
",",
" ")
1046 args[
"examples"] =
"ON" if args[
"examples"] ==
"True" else "OFF"
1047 args[
"tests"] =
"ON" if args[
"tests"] ==
"True" else "OFF"
1049 formatted_string = ns3rc_str.ns3rc_templates[self.
typetype].format(**args)
1052 return formatted_string
1056 return ns3rc_str.ns3rc_templates.keys()
1058 for ns3rc_type
in ns3rc_str.types():
1060 ns3rc_template = ns3rc_str(ns3rc_type)
1063 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1064 f.write(ns3rc_template.format(modules=
"'lte'", examples=
"False", tests=
"True"))
1067 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1068 self.
config_okconfig_ok(return_code, stdout, stderr)
1073 self.assertIn(
"ns3-lte", enabled_modules)
1078 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1079 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
1082 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1083 self.
config_okconfig_ok(return_code, stdout, stderr)
1088 self.assertIn(
"ns3-wifi", enabled_modules)
1093 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1095 ns3rc_template.format(
1096 modules=
"'core','network'", examples=
"True", tests=
"False"
1101 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1102 self.
config_okconfig_ok(return_code, stdout, stderr)
1107 self.assertIn(
"ns3-core", enabled_modules)
1108 self.assertIn(
"ns3-network", enabled_modules)
1114 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1115 if ns3rc_type ==
"python":
1117 ns3rc_template.format(
1118 modules=
"""'core', #comment
1122 'network', 'internet','wimax'""",
1129 ns3rc_template.format(
1130 modules=
"'core', 'lte', 'network', 'internet', 'wimax'",
1136 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1137 self.
config_okconfig_ok(return_code, stdout, stderr)
1142 self.assertIn(
"ns3-core", enabled_modules)
1143 self.assertIn(
"ns3-internet", enabled_modules)
1144 self.assertIn(
"ns3-lte", enabled_modules)
1145 self.assertIn(
"ns3-wimax", enabled_modules)
1150 os.remove(ns3rc_script)
1153 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1154 self.
config_okconfig_ok(return_code, stdout, stderr)
1163 Test dry-run (printing commands to be executed instead of running them)
1169 for positional_command
in [
"configure",
"build",
"clean"]:
1170 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
1171 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
1173 self.assertEqual(return_code, return_code1)
1174 self.assertEqual(stdout, stdout1)
1175 self.assertEqual(stderr, stderr1)
1180 run_ns3(
'configure -G "{generator}" -d release --enable-verbose')
1181 run_ns3(
"build scratch-simulator")
1184 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
1185 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
1186 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
1187 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
1190 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
1191 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
1195 if "scratch-simulator" in program
and "subdir" not in program:
1196 scratch_path = program
1202 self.assertIn(scratch_path, stdout0)
1206 self.assertIn(
"Built target", stdout1)
1207 self.assertNotIn(scratch_path, stdout1)
1210 self.assertIn(
"The following commands would be executed:", stdout2)
1211 self.assertIn(scratch_path, stdout2)
1214 self.assertNotIn(
"Finished executing the following commands:", stdout3)
1215 self.assertNotIn(scratch_path, stdout3)
1219 Test if ns3 is propagating back the return code from the executables called with the run command
1223 return_code, _, _ =
run_ns3(
"clean")
1224 self.assertEqual(return_code, 0)
1226 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-examples --enable-tests')
1227 self.assertEqual(return_code, 0)
1230 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
1231 self.assertEqual(return_code, 0)
1234 return_code, stdout, stderr =
run_ns3(
1235 'run "test-runner --test-name=command-line" --no-build'
1237 self.assertEqual(return_code, 0)
1240 return_code, stdout, stderr =
run_ns3(
1241 'run "test-runner --test-name=command-line" --no-build',
1242 env={
"NS_COMMANDLINE_INTROSPECTION":
".."},
1244 self.assertNotEqual(return_code, 0)
1247 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
1248 with open(sigsegv_example,
"w", encoding=
"utf-8")
as f:
1251 int main (int argc, char *argv[])
1253 char *s = "hello world"; *s = 'H';
1258 return_code, stdout, stderr =
run_ns3(
"run sigsegv")
1260 self.assertEqual(return_code, 4294967295)
1261 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1263 self.assertEqual(return_code, 245)
1264 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1267 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1268 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1271 #include "ns3/core-module.h"
1273 using namespace ns3;
1274 int main (int argc, char *argv[])
1281 return_code, stdout, stderr =
run_ns3(
"run abort")
1283 self.assertEqual(return_code, 3)
1284 self.assertIn(
"abort-default.exe' returned non-zero exit status", stdout)
1286 self.assertEqual(return_code, 250)
1287 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
1289 os.remove(sigsegv_example)
1290 os.remove(abort_example)
1294 Test passing 'show config' argument to ns3 to get the configuration table
1297 return_code, stdout, stderr =
run_ns3(
"show config")
1298 self.assertEqual(return_code, 0)
1299 self.assertIn(
"Summary of ns-3 settings", stdout)
1303 Test passing 'show profile' argument to ns3 to get the build profile
1306 return_code, stdout, stderr =
run_ns3(
"show profile")
1307 self.assertEqual(return_code, 0)
1308 self.assertIn(
"Build profile: release", stdout)
1312 Test passing 'show version' argument to ns3 to get the build version
1315 if shutil.which(
"git")
is None:
1316 self.skipTest(
"git is not available")
1318 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-build-version')
1319 self.assertEqual(return_code, 0)
1321 return_code, stdout, stderr =
run_ns3(
"show version")
1322 self.assertEqual(return_code, 0)
1323 self.assertIn(
"ns-3 version:", stdout)
1327 Test if CMake target names for scratches and ns3 shortcuts
1328 are working correctly
1335 "scratch/subdir1/main.cc",
1336 "scratch/subdir2/main.cc",
1337 "scratch/main.test.dots.in.name.cc",
1339 backup_files = [
"scratch/.main.cc"]
1342 for path
in test_files + backup_files:
1343 filepath = os.path.join(ns3_path, path)
1344 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
1345 with open(filepath,
"w", encoding=
"utf-8")
as f:
1347 f.write(
"int main (int argc, char *argv[]){}")
1355 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1356 self.assertEqual(return_code, 0)
1359 for path
in test_files + backup_files:
1360 path = path.replace(
".cc",
"")
1363 "--build . --target %s -j %d" % (path.replace(
"/",
"_"), num_threads),
1364 cwd=os.path.join(ns3_path,
"cmake-cache"),
1366 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
1367 if "main" in path
and ".main" not in path:
1368 self.assertEqual(return_code1, 0)
1369 self.assertEqual(return_code2, 0)
1371 self.assertEqual(return_code1, 2)
1372 self.assertEqual(return_code2, 1)
1375 for path
in test_files:
1376 path = path.replace(
".cc",
"")
1377 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
1379 self.assertEqual(return_code, 0)
1381 self.assertEqual(return_code, 1)
1385 container.execute(
"apt-get update")
1386 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
1389 "./ns3 configure --enable-modules=core,network,internet -- -DCMAKE_CXX_COMPILER=/usr/bin/g++"
1391 except DockerException
as e:
1393 for path
in test_files:
1394 path = path.replace(
".cc",
"")
1396 container.execute(f
"./ns3 run {path}")
1397 except DockerException
as e:
1403 for path
in test_files + backup_files:
1404 source_absolute_path = os.path.join(ns3_path, path)
1405 os.remove(source_absolute_path)
1406 if "empty" in path
or ".main" in path:
1408 filename = os.path.basename(path).replace(
".cc",
"")
1409 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
1410 if os.path.exists(executable_absolute_path):
1411 executable_name =
list(
1412 filter(
lambda x: filename
in x, os.listdir(executable_absolute_path))
1415 os.remove(os.path.join(executable_absolute_path, executable_name))
1416 if not os.listdir(os.path.dirname(path)):
1417 os.rmdir(os.path.dirname(source_absolute_path))
1419 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1420 self.assertEqual(return_code, 0)
1424 Test if ns3 is inserting additional arguments by MPICH and OpenMPI to run on the CI
1428 if shutil.which(
"mpiexec")
is None or win32:
1429 self.skipTest(
"Mpi is not available")
1431 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1432 self.assertEqual(return_code, 0)
1436 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
1437 self.assertEqual(return_code, 0)
1440 sample_simulator_path =
list(filter(
lambda x:
"sample-simulator" in x, executables))[0]
1442 mpi_command =
'--dry-run run sample-simulator --command-template="mpiexec -np 2 %s"'
1443 non_mpi_command =
'--dry-run run sample-simulator --command-template="echo %s"'
1446 return_code, stdout, stderr =
run_ns3(mpi_command)
1447 self.assertEqual(return_code, 0)
1448 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1451 return_code, stdout, stderr =
run_ns3(mpi_command)
1452 self.assertEqual(return_code, 0)
1453 if os.getenv(
"USER",
"") ==
"root":
1454 if shutil.which(
"ompi_info"):
1456 "mpiexec --allow-run-as-root --oversubscribe -np 2 %s" % sample_simulator_path,
1461 "mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout
1464 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1467 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1468 self.assertEqual(return_code, 0)
1469 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1472 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1473 self.assertEqual(return_code, 0)
1474 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1476 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1477 self.assertEqual(return_code, 0)
1481 Test if CMake and ns3 fail in the expected ways when:
1482 - examples from modules or general examples fail if they depend on a
1483 library with a name shorter than 4 characters or are disabled when
1484 a library is nonexistent
1485 - a module library passes the configuration but fails to build due to
1489 os.makedirs(
"contrib/borked", exist_ok=
True)
1490 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1493 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1495 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1496 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1501 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1502 LIBRARIES_TO_LINK ${libcore} %s
1505 % invalid_or_nonexistent_library
1508 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1509 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1510 self.assertEqual(return_code, 0)
1511 elif invalid_or_nonexistent_library
in [
"lib"]:
1512 self.assertEqual(return_code, 1)
1513 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1517 return_code, stdout, stderr =
run_ns3(
"build borked")
1518 if invalid_or_nonexistent_library
in [
""]:
1519 self.assertEqual(return_code, 0)
1520 elif invalid_or_nonexistent_library
in [
"lib"]:
1521 self.assertEqual(return_code, 2)
1522 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1523 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1524 self.assertEqual(return_code, 2)
1525 if "lld" in stdout + stderr:
1527 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1529 elif "mold" in stdout + stderr:
1530 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1532 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1540 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1545 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1546 LIBRARIES_TO_LINK ${libcore}
1550 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1551 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1556 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1557 LIBRARIES_TO_LINK ${libborked} %s
1560 % invalid_or_nonexistent_library
1563 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1564 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1565 self.assertEqual(return_code, 0)
1566 elif invalid_or_nonexistent_library
in [
"lib"]:
1567 self.assertEqual(return_code, 1)
1568 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1572 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1573 if invalid_or_nonexistent_library
in [
""]:
1574 self.assertEqual(return_code, 0)
1575 elif invalid_or_nonexistent_library
in [
"libf"]:
1576 self.assertEqual(return_code, 2)
1577 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1578 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1579 self.assertEqual(return_code, 1)
1580 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1584 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1588 Test if CMake can properly handle modules containing "lib",
1589 which is used internally as a prefix for module libraries
1593 os.makedirs(
"contrib/calibre", exist_ok=
True)
1594 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1597 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1599 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1604 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1605 LIBRARIES_TO_LINK ${libcore}
1610 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1613 self.assertEqual(return_code, 0)
1616 self.assertIn(
"calibre", stdout)
1620 self.assertNotIn(
"care", stdout)
1622 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1626 return_code, stdout, stderr =
run_ns3(
"build calibre")
1627 self.assertEqual(return_code, 0)
1630 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1634 Test if CMake performance tracing works and produces the
1635 cmake_performance_trace.log file
1638 cmake_performance_trace_log = os.path.join(ns3_path,
"cmake_performance_trace.log")
1639 if os.path.exists(cmake_performance_trace_log):
1640 os.remove(cmake_performance_trace_log)
1642 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1643 self.assertEqual(return_code, 0)
1645 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1648 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1651 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1655 Check if ENABLE_BUILD_VERSION and version.cache are working
1663 container.execute(
"apt-get update")
1664 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1667 container.execute(
"./ns3 clean")
1670 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1673 if os.path.exists(version_cache_file):
1674 os.remove(version_cache_file)
1678 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1679 except DockerException:
1681 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1684 version_cache_contents = (
1685 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1686 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1687 "VERSION_DIRTY_FLAG = '0'\n"
1688 "VERSION_MAJOR = '3'\n"
1689 "VERSION_MINOR = '0'\n"
1690 "VERSION_PATCH = '0'\n"
1691 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1692 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1693 "VERSION_TAG_DISTANCE = '0'\n"
1694 "VERSION_BUILD_PROFILE = 'debug'\n"
1696 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1697 version.write(version_cache_contents)
1700 container.execute(
"./ns3 clean")
1701 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1702 container.execute(
"./ns3 build core")
1703 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1706 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1707 self.assertEqual(version.read(), version_cache_contents)
1712 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1714 container.execute(
"apt-get install -y git")
1715 container.execute(
"./ns3 clean")
1716 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1717 container.execute(
"./ns3 build core")
1718 except DockerException:
1720 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1721 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1724 container.execute(
"./ns3 clean")
1725 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1726 container.execute(
"./ns3 build core")
1727 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1728 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1729 self.assertNotEqual(version.read(), version_cache_contents)
1732 if os.path.exists(version_cache_file):
1733 os.remove(version_cache_file)
1737 Test filtering in examples and tests from specific modules
1741 return_code, stdout, stderr =
run_ns3(
1742 'configure -G "{generator}" --enable-examples --enable-tests'
1744 self.
config_okconfig_ok(return_code, stdout, stderr)
1749 return_code, stdout, stderr =
run_ns3(
1750 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1752 self.
config_okconfig_ok(return_code, stdout, stderr)
1758 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1760 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1763 return_code, stdout, stderr =
run_ns3(
1764 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1766 self.
config_okconfig_ok(return_code, stdout, stderr)
1774 return_code, stdout, stderr =
run_ns3(
1775 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1777 self.
config_okconfig_ok(return_code, stdout, stderr)
1785 Check if fast linkers LLD and Mold are correctly found and configured
1792 container.execute(
"apt-get update")
1793 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1796 container.execute(
"./ns3 configure -G Ninja")
1799 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1801 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1803 self.assertIn(
"-fuse-ld=lld", f.read())
1807 container.execute(
"./ns3 build core")
1808 except DockerException:
1809 self.assertTrue(
False,
"Build with lld failed")
1812 if not os.path.exists(
"./mold-1.4.2-x86_64-linux.tar.gz"):
1814 "wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-x86_64-linux.tar.gz"
1817 "tar xzfC mold-1.4.2-x86_64-linux.tar.gz /usr/local --strip-components=1"
1822 container.execute(
"./ns3 configure -G Ninja")
1825 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1827 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1829 self.assertIn(
"-fuse-ld=mold", f.read())
1833 container.execute(
"./ns3 build core")
1834 except DockerException:
1835 self.assertTrue(
False,
"Build with mold failed")
1838 os.remove(
"./mold-1.4.2-x86_64-linux.tar.gz")
1841 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1844 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1846 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1848 self.assertNotIn(
"-fuse-ld=mold", f.read())
1852 Check if NS3_CLANG_TIMETRACE feature is working
1853 Clang's -ftime-trace plus ClangAnalyzer report
1859 container.execute(
"apt-get update")
1860 container.execute(
"apt-get install -y python3 ninja-build cmake clang-10")
1865 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DNS3_CLANG_TIMETRACE=ON"
1867 except DockerException
as e:
1868 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1870 container.execute(
"apt-get install -y git")
1875 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DNS3_CLANG_TIMETRACE=ON"
1877 except DockerException
as e:
1878 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1881 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1882 if os.path.exists(time_trace_report_path):
1883 os.remove(time_trace_report_path)
1887 container.execute(
"./ns3 build timeTraceReport")
1888 except DockerException
as e:
1889 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1892 self.assertTrue(os.path.exists(time_trace_report_path))
1896 container.execute(
"apt-get install -y g++")
1897 container.execute(
"apt-get remove -y clang-10")
1901 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1904 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1906 except DockerException
as e:
1907 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1911 Check if NS3_NINJA_TRACE feature is working
1912 Ninja's .ninja_log conversion to about://tracing
1913 json format conversion with Ninjatracing
1919 container.execute(
"apt-get update")
1920 container.execute(
"apt-get install -y python3 cmake clang-10")
1925 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10"
1927 except DockerException
as e:
1928 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1933 container.execute(
"apt-get install -y ninja-build")
1937 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10"
1939 except DockerException
as e:
1940 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1942 container.execute(
"apt-get install -y git")
1946 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10"
1948 except DockerException
as e:
1949 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1952 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1953 if os.path.exists(ninja_trace_path):
1954 os.remove(ninja_trace_path)
1957 container.execute(
"./ns3 build core")
1961 container.execute(
"./ns3 build ninjaTrace")
1962 except DockerException
as e:
1963 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1966 self.assertTrue(os.path.exists(ninja_trace_path))
1967 trace_size = os.stat(ninja_trace_path).st_size
1968 os.remove(ninja_trace_path)
1975 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DNS3_CLANG_TIMETRACE=ON"
1977 except DockerException
as e:
1978 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
1981 container.execute(
"./ns3 build core")
1985 container.execute(
"./ns3 build ninjaTrace")
1986 except DockerException
as e:
1987 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1989 self.assertTrue(os.path.exists(ninja_trace_path))
1990 timetrace_size = os.stat(ninja_trace_path).st_size
1991 os.remove(ninja_trace_path)
1994 self.assertGreater(timetrace_size, trace_size)
1998 Check if precompiled headers are being enabled correctly.
2008 container.execute(
"apt-get update")
2009 container.execute(
"apt-get install -y python3 cmake ccache g++")
2011 container.execute(
"./ns3 configure")
2012 except DockerException
as e:
2013 self.assertIn(
"incompatible with ccache", e.stderr)
2020 container.execute(
"apt-get update")
2021 container.execute(
"apt-get install -y python3 cmake ccache g++")
2023 container.execute(
"./ns3 configure")
2024 except DockerException
as e:
2025 self.assertTrue(
False,
"Precompiled headers should have been enabled")
2029 Check for regressions in test object build.
2032 return_code, stdout, stderr =
run_ns3(
"configure")
2033 self.assertEqual(return_code, 0)
2035 test_module_cache = os.path.join(ns3_path,
"cmake-cache",
"src",
"test")
2036 self.assertFalse(os.path.exists(test_module_cache))
2038 return_code, stdout, stderr =
run_ns3(
"configure --enable-tests")
2039 self.assertEqual(return_code, 0)
2040 self.assertTrue(os.path.exists(test_module_cache))
2044 Check for regressions in a bare ns-3 configuration.
2051 container.execute(
"apt-get update")
2052 container.execute(
"apt-get install -y python3 cmake g++")
2056 stdout = container.execute(
"./ns3 configure -d release")
2057 except DockerException
as e:
2059 self.
config_okconfig_ok(return_code, stdout, stdout)
2066 Tests ns3 regarding building the project
2071 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2080 Try building the core library
2083 return_code, stdout, stderr =
run_ns3(
"build core")
2084 self.assertEqual(return_code, 0)
2085 self.assertIn(
"Built target libcore", stdout)
2089 Try building core-test library without tests enabled
2093 return_code, stdout, stderr =
run_ns3(
"build core-test")
2094 self.assertEqual(return_code, 1)
2095 self.assertIn(
"Target to build does not exist: core-test", stdout)
2099 Try building the project:
2102 return_code, stdout, stderr =
run_ns3(
"build")
2103 self.assertEqual(return_code, 0)
2104 self.assertIn(
"Built target", stdout)
2106 self.assertTrue(os.path.exists(program), program)
2107 self.assertIn(cmake_build_project_command, stdout)
2111 Try hiding task lines
2114 return_code, stdout, stderr =
run_ns3(
"--quiet build")
2115 self.assertEqual(return_code, 0)
2116 self.assertIn(cmake_build_project_command, stdout)
2120 Try removing an essential file to break the build
2124 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
2125 attribute_cc_bak_path = attribute_cc_path +
".bak"
2126 shutil.move(attribute_cc_path, attribute_cc_bak_path)
2129 return_code, stdout, stderr =
run_ns3(
"build")
2130 self.assertNotEqual(return_code, 0)
2133 shutil.move(attribute_cc_bak_path, attribute_cc_path)
2136 return_code, stdout, stderr =
run_ns3(
"build")
2137 self.assertEqual(return_code, 0)
2141 Test if changing the version file affects the library names
2147 version_file = os.sep.join([ns3_path,
"VERSION"])
2148 with open(version_file,
"w", encoding=
"utf-8")
as f:
2152 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
2153 self.
config_okconfig_ok(return_code, stdout, stderr)
2156 return_code, stdout, stderr =
run_ns3(
"build")
2157 self.assertEqual(return_code, 0)
2158 self.assertIn(
"Built target", stdout)
2164 for program
in new_programs:
2165 self.assertTrue(os.path.exists(program))
2172 new_libraries =
list(set(libraries).difference(set(self.
ns3_librariesns3_libraries)))
2173 self.assertEqual(len(new_libraries), len(self.
ns3_librariesns3_libraries))
2174 for library
in new_libraries:
2175 self.assertNotIn(
"libns3-dev", library)
2176 self.assertIn(
"libns3-00", library)
2177 self.assertTrue(os.path.exists(library))
2180 with open(version_file,
"w", encoding=
"utf-8")
as f:
2185 Try setting a different output directory and if everything is
2186 in the right place and still working correctly
2191 return_code, stdout, stderr =
run_ns3(
"build")
2192 self.assertEqual(return_code, 0)
2207 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
2208 relative_path = os.sep.join([
"build",
"release"])
2209 for different_out_dir
in [absolute_path, relative_path]:
2210 return_code, stdout, stderr =
run_ns3(
2211 'configure -G "{generator}" --out=%s' % different_out_dir
2213 self.
config_okconfig_ok(return_code, stdout, stderr)
2215 "Build directory : %s" % absolute_path.replace(os.sep,
"/"), stdout
2224 for program
in new_programs:
2225 self.assertTrue(os.path.exists(program))
2229 new_libraries =
list(set(libraries).difference(set(self.
ns3_librariesns3_libraries)))
2230 self.assertEqual(len(new_libraries), len(self.
ns3_librariesns3_libraries))
2231 for library
in new_libraries:
2232 self.assertTrue(os.path.exists(library))
2235 shutil.rmtree(absolute_path)
2238 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --out=''")
2239 self.
config_okconfig_ok(return_code, stdout, stderr)
2241 "Build directory : %s" % usual_outdir.replace(os.sep,
"/"), stdout
2250 for program
in new_programs:
2251 self.assertTrue(os.path.exists(program))
2255 self.assertEqual(len(libraries), len(self.
ns3_librariesns3_libraries))
2256 for library
in libraries:
2257 self.assertTrue(os.path.exists(library))
2261 Tries setting a ns3 version, then installing it.
2262 After that, tries searching for ns-3 with CMake's find_package(ns3).
2263 Finally, tries using core library in a 3rd-party project
2268 for library
in libraries:
2272 version_file = os.sep.join([ns3_path,
"VERSION"])
2273 with open(version_file,
"w", encoding=
"utf-8")
as f:
2277 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
2278 return_code, stdout, stderr =
run_ns3(
2279 'configure -G "{generator}" --prefix=%s' % install_prefix
2281 self.
config_okconfig_ok(return_code, stdout, stderr)
2292 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
2293 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
2297 installed_libraries_list =
";".join(installed_libraries)
2298 for library
in libraries:
2299 library_name = os.path.basename(library)
2300 self.assertIn(library_name, installed_libraries_list)
2304 missing_headers =
list(
2305 set([os.path.basename(x)
for x
in headers])
2306 - (set([os.path.basename(x)
for x
in installed_headers]))
2308 self.assertEqual(len(missing_headers), 0)
2311 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
2312 with open(test_main_file,
"w", encoding=
"utf-8")
as f:
2315 #include <ns3/core-module.h>
2316 using namespace ns3;
2319 Simulator::Stop (Seconds (1.0));
2321 Simulator::Destroy ();
2330 for version
in [
"",
"3.01",
"3.00"]:
2331 ns3_import_methods = []
2334 cmake_find_package_import =
"""
2335 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
2336 find_package(ns3 {version} COMPONENTS libcore)
2337 target_link_libraries(test PRIVATE ns3::libcore)
2339 lib=(
"lib64" if lib64
else "lib"), version=version
2341 ns3_import_methods.append(cmake_find_package_import)
2344 pkgconfig_import =
"""
2345 list(APPEND CMAKE_PREFIX_PATH ./)
2346 include(FindPkgConfig)
2347 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
2348 target_link_libraries(test PUBLIC PkgConfig::ns3)
2350 lib=(
"lib64" if lib64
else "lib"), version=
"=" + version
if version
else ""
2352 if shutil.which(
"pkg-config"):
2353 ns3_import_methods.append(pkgconfig_import)
2356 for import_method
in ns3_import_methods:
2357 test_cmake_project = (
2359 cmake_minimum_required(VERSION 3.12..3.12)
2360 project(ns3_consumer CXX)
2361 set(CMAKE_CXX_STANDARD 20)
2362 set(CMAKE_CXX_STANDARD_REQUIRED ON)
2363 add_executable(test main.cpp)
2368 test_cmake_project_file = os.sep.join([install_prefix,
"CMakeLists.txt"])
2369 with open(test_cmake_project_file,
"w", encoding=
"utf-8")
as f:
2370 f.write(test_cmake_project)
2373 cmake = shutil.which(
"cmake")
2376 '-DCMAKE_BUILD_TYPE=debug -G"{generator}" .'.format(
2377 generator=platform_makefiles
2382 if version ==
"3.00":
2383 self.assertEqual(return_code, 1)
2384 if import_method == cmake_find_package_import:
2386 'Could not find a configuration file for package "ns3" that is compatible',
2387 stderr.replace(
"\n",
""),
2389 elif import_method == pkgconfig_import:
2390 self.assertIn(
"A required package was not found", stderr.replace(
"\n",
""))
2392 raise Exception(
"Unknown import type")
2394 self.assertEqual(return_code, 0)
2395 self.assertIn(
"Build files", stdout)
2398 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
2400 if version ==
"3.00":
2401 self.assertEqual(return_code, 2)
2402 self.assertGreater(len(stderr), 0)
2404 self.assertEqual(return_code, 0)
2405 self.assertIn(
"Built target", stdout)
2409 test_program = os.path.join(install_prefix,
"test.exe")
2410 env_sep =
";" if ";" in os.environ[
"PATH"]
else ":"
2412 "PATH": env_sep.join(
2413 [os.environ[
"PATH"], os.path.join(install_prefix,
"lib")]
2417 test_program =
"./test"
2420 test_program,
"", cwd=install_prefix, env=env
2422 self.assertEqual(return_code, 0)
2425 return_code, stdout, stderr =
run_ns3(
"uninstall")
2426 self.assertIn(
"Built target uninstall", stdout)
2429 os.remove(version_file)
2430 with open(version_file,
"w", encoding=
"utf-8")
as f:
2435 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
2440 "scratch/scratch-simulator":
"scratch-simulator",
2441 "scratch/scratch-simulator.cc":
"scratch-simulator",
2442 "scratch-simulator":
"scratch-simulator",
2443 "scratch/subdir/scratch-subdir":
"subdir_scratch-subdir",
2444 "subdir/scratch-subdir":
"subdir_scratch-subdir",
2445 "scratch-subdir":
"subdir_scratch-subdir",
2447 for target_to_run, target_cmake
in targets.items():
2449 build_line =
"target scratch_%s" % target_cmake
2450 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
2451 self.assertEqual(return_code, 0)
2452 self.assertIn(build_line, stdout)
2455 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
2456 self.assertEqual(return_code, 0)
2457 self.assertIn(build_line, stdout)
2458 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
2459 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
2463 Test if ns3 can alert correctly in case a shortcut collision happens
2468 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2469 self.assertEqual(return_code, 0)
2472 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
2475 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
2476 self.assertEqual(return_code, 0)
2479 return_code, stdout, stderr =
run_ns3(
"build second")
2480 self.assertEqual(return_code, 1)
2482 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2483 stdout.replace(os.sep,
"/"),
2487 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
2488 self.assertEqual(return_code, 0)
2492 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
2493 self.assertEqual(return_code, 0)
2497 return_code, stdout, stderr =
run_ns3(
"run second")
2498 self.assertEqual(return_code, 1)
2500 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
2501 stdout.replace(os.sep,
"/"),
2505 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
2506 self.assertEqual(return_code, 0)
2509 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
2510 self.assertEqual(return_code, 0)
2513 os.remove(
"./scratch/second.cc")
2517 Test if we can build a static ns-3 library and link it to static programs
2522 return_code, stdout, stderr =
run_ns3(
2523 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2529 self.assertEqual(return_code, 1)
2530 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2533 self.assertEqual(return_code, 0)
2536 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2537 self.assertEqual(return_code, 0)
2538 self.assertIn(
"Built target", stdout)
2544 Test if we can use python bindings
2549 except ModuleNotFoundError:
2550 self.skipTest(
"Cppyy was not found")
2553 return_code, stdout, stderr =
run_ns3(
2554 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2558 self.assertEqual(return_code, 0)
2561 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2562 self.assertEqual(return_code, 0)
2565 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2566 self.assertEqual(return_code, 0)
2570 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2572 self.assertEqual(return_code, 0)
2576 Test if we had regressions with brite, click and openflow modules
2577 that depend on homonymous libraries
2580 if shutil.which(
"git")
is None:
2581 self.skipTest(
"Missing git")
2584 return_code, stdout, stderr =
run_ns3(
"configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON")
2585 self.assertEqual(return_code, 0)
2589 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2590 self.assertEqual(return_code, 0)
2594 Test if we can link contrib modules to src modules
2597 if shutil.which(
"git")
is None:
2598 self.skipTest(
"Missing git")
2600 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2601 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2603 if os.path.exists(destination_contrib):
2604 shutil.rmtree(destination_contrib)
2605 if os.path.exists(destination_src):
2606 shutil.rmtree(destination_src)
2610 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2611 destination_contrib,
2614 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2619 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2620 self.assertEqual(return_code, 0)
2623 return_code, stdout, stderr =
run_ns3(
"run source-example")
2624 self.assertEqual(return_code, 0)
2627 shutil.rmtree(destination_contrib)
2628 shutil.rmtree(destination_src)
2633 Tests ns3 usage in more realistic scenarios
2638 Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned
2639 Here examples, tests and documentation are also enabled.
2646 return_code, stdout, stderr =
run_ns3(
2647 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2649 self.
config_okconfig_ok(return_code, stdout, stderr)
2652 self.assertTrue(os.path.exists(ns3_lock_filename))
2658 self.assertTrue(os.path.exists(ns3_lock_filename))
2665 Try to build the project
2668 return_code, stdout, stderr =
run_ns3(
"build")
2669 self.assertEqual(return_code, 0)
2670 self.assertIn(
"Built target", stdout)
2672 self.assertTrue(os.path.exists(program))
2675 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2676 self.assertIn(cmake_build_project_command, stdout)
2680 Try to build and run test-runner
2683 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --verbose')
2684 self.assertEqual(return_code, 0)
2685 self.assertIn(
"Built target test-runner", stdout)
2690 Try to build and run a library
2693 return_code, stdout, stderr =
run_ns3(
"run core")
2694 self.assertEqual(return_code, 1)
2695 self.assertIn(
"Couldn't find the specified program: core", stderr)
2699 Try to build and run an unknown target
2702 return_code, stdout, stderr =
run_ns3(
"run nonsense")
2703 self.assertEqual(return_code, 1)
2704 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2708 Try to run test-runner without building
2711 return_code, stdout, stderr =
run_ns3(
"build test-runner")
2712 self.assertEqual(return_code, 0)
2714 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2715 self.assertEqual(return_code, 0)
2716 self.assertNotIn(
"Built target test-runner", stdout)
2721 Test ns3 fails to run a library
2724 return_code, stdout, stderr =
run_ns3(
"run core --no-build")
2725 self.assertEqual(return_code, 1)
2726 self.assertIn(
"Couldn't find the specified program: core", stderr)
2730 Test ns3 fails to run an unknown program
2733 return_code, stdout, stderr =
run_ns3(
"run nonsense --no-build")
2734 self.assertEqual(return_code, 1)
2735 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2739 Test if scratch simulator is executed through gdb and lldb
2742 if shutil.which(
"gdb")
is None:
2743 self.skipTest(
"Missing gdb")
2745 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2746 self.assertEqual(return_code, 0)
2748 return_code, stdout, stderr =
run_ns3(
2749 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2751 self.assertEqual(return_code, 0)
2752 self.assertIn(
"scratch-simulator", stdout)
2754 self.assertIn(
"GNU gdb", stdout)
2756 self.assertIn(
"No debugging symbols found", stdout)
2760 Test if scratch simulator is executed through valgrind
2763 if shutil.which(
"valgrind")
is None:
2764 self.skipTest(
"Missing valgrind")
2766 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2767 self.assertEqual(return_code, 0)
2769 return_code, stdout, stderr =
run_ns3(
2770 "run scratch-simulator --valgrind --verbose --no-build"
2772 self.assertEqual(return_code, 0)
2773 self.assertIn(
"scratch-simulator", stderr)
2774 self.assertIn(
"Memcheck", stderr)
2778 Test the doxygen target that does trigger a full build
2781 if shutil.which(
"doxygen")
is None:
2782 self.skipTest(
"Missing doxygen")
2784 if shutil.which(
"bash")
is None:
2785 self.skipTest(
"Missing bash")
2787 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2789 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2790 for filename
in doxygen_files:
2791 file_path = os.sep.join([doc_folder, filename])
2792 if os.path.exists(file_path):
2793 os.remove(file_path)
2800 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2801 self.assertEqual(return_code, 0)
2803 self.assertIn(
"Built target doxygen", stdout)
2807 Test the doxygen target that doesn't trigger a full build
2810 if shutil.which(
"doxygen")
is None:
2811 self.skipTest(
"Missing doxygen")
2819 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2820 self.assertEqual(return_code, 0)
2822 self.assertIn(
"Built target doxygen-no-build", stdout)
2826 Test every individual target for Sphinx-based documentation
2829 if shutil.which(
"sphinx-build")
is None:
2830 self.skipTest(
"Missing sphinx")
2832 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2835 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2837 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2838 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2839 if os.path.exists(doc_build_folder):
2840 shutil.rmtree(doc_build_folder)
2841 if os.path.exists(doc_temp_folder):
2842 shutil.rmtree(doc_temp_folder)
2845 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2846 self.assertEqual(return_code, 0, target)
2848 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2851 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2852 self.assertTrue(os.path.exists(doc_build_folder))
2855 for build_type
in [
"latex",
"html",
"singlehtml"]:
2856 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2860 Test the documentation target that builds
2861 both doxygen and sphinx based documentation
2864 if shutil.which(
"doxygen")
is None:
2865 self.skipTest(
"Missing doxygen")
2866 if shutil.which(
"sphinx-build")
is None:
2867 self.skipTest(
"Missing sphinx")
2869 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2878 for target
in [
"manual",
"models",
"tutorial"]:
2879 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2880 if os.path.exists(doc_build_folder):
2881 shutil.rmtree(doc_build_folder)
2883 return_code, stdout, stderr =
run_ns3(
"docs all")
2884 self.assertEqual(return_code, 0)
2886 self.assertIn(
"Built target sphinx", stdout)
2888 self.assertIn(
"Built target doxygen", stdout)
2892 Try to set ownership of scratch-simulator from current user to root,
2893 and change execution permissions
2898 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2901 if sudo_password
is None:
2902 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2905 self.assertFalse(enable_sudo
is True)
2908 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2909 self.assertEqual(return_code, 0)
2910 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2912 scratch_simulator_path =
list(
2915 prev_fstat = os.stat(scratch_simulator_path)
2918 return_code, stdout, stderr =
run_ns3(
2919 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2921 self.assertEqual(return_code, 0)
2922 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2924 fstat = os.stat(scratch_simulator_path)
2930 likely_fuse_mount = (
2931 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2932 )
and prev_fstat.st_uid == 0
2934 if win32
or likely_fuse_mount:
2935 self.skipTest(
"Windows or likely a FUSE mount")
2938 self.assertEqual(fstat.st_uid, 0)
2940 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2944 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2945 self.assertEqual(return_code, 0)
2949 self.assertTrue(enable_sudo)
2953 if os.path.exists(executable):
2954 os.remove(executable)
2957 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2958 self.assertEqual(return_code, 0)
2961 self.assertIn(
"chown root", stdout)
2962 self.assertIn(
"chmod u+s", stdout)
2964 self.assertIn(os.path.basename(executable), stdout)
2967 fstat = os.stat(scratch_simulator_path)
2968 self.assertEqual(fstat.st_uid, 0)
2970 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2975 Check if command template is working
2980 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
2981 self.assertEqual(return_code0, 2)
2982 self.assertIn(
"argument --command-template: expected one argument", stderr0)
2984 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
2985 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
2986 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
2987 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
2988 for stderr
in [stderr1, stderr2, stderr3]:
2989 self.assertIn(
"not all arguments converted during string formatting", stderr)
2992 return_code4, stdout4, _ =
run_ns3(
2993 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
2995 return_code5, stdout5, _ =
run_ns3(
2996 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
2998 self.assertEqual((return_code4, return_code5), (0, 0))
3000 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3001 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3005 Check if all flavors of different argument passing to
3006 executable targets are working
3011 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3012 return_code1, stdout1, stderr1 =
run_ns3(
3013 'run sample-simulator --command-template="%s --help" --verbose'
3015 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3017 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3018 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3019 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3020 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3023 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3024 return_code1, stdout1, stderr1 =
run_ns3(
3025 'run sample-simulator --command-template="%s --help" --no-build'
3027 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3028 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3029 self.assertEqual(stdout0, stdout1)
3030 self.assertEqual(stdout1, stdout2)
3031 self.assertEqual(stderr0, stderr1)
3032 self.assertEqual(stderr1, stderr2)
3035 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3036 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3037 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3039 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3040 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3041 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3042 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3045 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3046 return_code, stdout, stderr =
run_ns3(cmd)
3047 self.assertEqual(return_code, 0)
3053 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3058 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3059 cmd1 =
"run sample-simulator --PrintTypeIds"
3061 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3062 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3063 self.assertEqual((return_code0, return_code1), (1, 1))
3064 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3065 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3069 Test if scratch simulator is executed through lldb
3072 if shutil.which(
"lldb")
is None:
3073 self.skipTest(
"Missing lldb")
3075 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3076 self.assertEqual(return_code, 0)
3078 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3079 self.assertEqual(return_code, 0)
3080 self.assertIn(
"scratch-simulator", stdout)
3081 self.assertIn(
"(lldb) target create", stdout)
3085 Test if CPM and Vcpkg package managers are working properly
3089 return_code, stdout, stderr =
run_ns3(
"clean")
3090 self.assertEqual(return_code, 0)
3093 if os.path.exists(
"vcpkg"):
3094 shutil.rmtree(
"vcpkg")
3097 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3099 if os.path.exists(destination_src):
3100 shutil.rmtree(destination_src)
3104 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3110 container.execute(
"apt-get update")
3111 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3116 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3117 self.skipTest(
"Armadillo is already installed")
3118 except DockerException
as e:
3122 return_code, stdout, stderr =
run_ns3(
"clean")
3123 self.assertEqual(return_code, 0)
3126 container.execute(
"apt-get install -y git")
3131 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3133 except DockerException
as e:
3138 container.execute(
"./ns3 build test-package-managers")
3139 except DockerException
as e:
3143 return_code, stdout, stderr =
run_ns3(
"clean")
3144 self.assertEqual(return_code, 0)
3147 container.execute(
"apt-get install -y zip unzip tar curl")
3150 container.execute(
"apt-get install -y pkg-config gfortran")
3154 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3155 except DockerException
as e:
3160 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3161 except DockerException
as e:
3166 container.execute(
"./ns3 build test-package-managers")
3167 except DockerException
as e:
3171 if os.path.exists(destination_src):
3172 shutil.rmtree(destination_src)
3177 ns-3 tests to control the quality of the repository over time,
3178 by checking the state of URLs listed and more
3183 Test if all urls in source files are alive
3192 self.skipTest(
"Django URL validators are not available")
3199 urllib3.disable_warnings()
3202 self.skipTest(
"Requests library is not available")
3204 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3207 whitelisted_urls = {
3208 "https://gitlab.com/your-user-name/ns-3-dev",
3209 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3210 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3211 "https://www.nsnam.org/releases/ns-3-x",
3212 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3213 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3214 "https://ns-buildmaster.ee.washington.edu:8010/",
3216 "https://cmake.org/cmake/help/latest/manual/cmake-",
3217 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3219 "http://www.lysator.liu.se/~alla/dia/",
3221 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3222 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3223 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3224 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3226 "http://www.research.att.com/info/kpv/",
3227 "http://www.research.att.com/~gsf/",
3228 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3229 "http://scan5.coverity.com/cgi-bin/upload.py",
3231 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3232 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3236 files_and_urls = set()
3238 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3239 for root, dirs, files
in os.walk(topdir):
3241 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3244 filepath = os.path.join(root, file)
3247 if not os.path.isfile(filepath):
3251 if file.endswith(
".svg"):
3255 with open(filepath,
"r", encoding=
"utf-8")
as f:
3256 matches = regex.findall(f.read())
3262 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3264 except UnicodeDecodeError:
3265 skipped_files.append(filepath)
3269 for url
in set(urls) - unique_urls - whitelisted_urls:
3270 unique_urls.add(url)
3271 files_and_urls.add((filepath, url))
3274 from django.core.exceptions
import ValidationError
3275 from django.core.validators
import URLValidator
3277 validate_url = URLValidator()
3281 "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"
3285 def test_file_url(args):
3286 test_filepath, test_url = args
3287 dead_link_msg =
None
3291 validate_url(test_url)
3292 except ValidationError:
3293 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3294 except Exception
as e:
3295 self.assertEqual(
False,
True, msg=e.__str__())
3297 if dead_link_msg
is not None:
3298 return dead_link_msg
3306 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3309 if response.status_code
in [200, 301]:
3310 dead_link_msg =
None
3315 if response.status_code
in [302, 308, 500, 503]:
3316 if response.reason.lower()
in [
3318 "moved temporarily",
3319 "permanent redirect",
3321 "service temporarily unavailable",
3323 dead_link_msg =
None
3327 dead_link_msg =
"%s: URL %s: returned code %d" % (
3330 response.status_code,
3332 except requests.exceptions.InvalidURL:
3333 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3334 except requests.exceptions.SSLError:
3335 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3336 except requests.exceptions.TooManyRedirects:
3337 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3338 except Exception
as e:
3340 error_msg = e.args[0].reason.__str__()
3341 except AttributeError:
3342 error_msg = e.args[0]
3343 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3349 return dead_link_msg
3352 from concurrent.futures
import ThreadPoolExecutor
3354 with ThreadPoolExecutor(max_workers=100)
as executor:
3355 dead_links =
list(executor.map(test_file_url,
list(files_and_urls)))
3358 dead_links =
list(sorted(filter(
lambda x: x
is not None, dead_links)))
3359 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3363 Test if all tests can be executed without hitting major memory bugs
3366 return_code, stdout, stderr =
run_ns3(
3367 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3369 self.assertEqual(return_code, 0)
3371 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3372 self.assertEqual(test_return_code, 0)
3376 Check if images in the docs are above a brightness threshold.
3377 This should prevent screenshots with dark UI themes.
3380 if shutil.which(
"convert")
is None:
3381 self.skipTest(
"Imagemagick was not found")
3383 from pathlib
import Path
3386 image_extensions = [
"png",
"jpg"]
3388 for extension
in image_extensions:
3389 images +=
list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3390 images +=
list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3393 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3397 brightness_threshold = 50
3398 for image
in images:
3399 brightness = subprocess.check_output(
3400 imagemagick_get_image_brightness.format(image=image).split()
3402 brightness = float(brightness.decode().strip(
"'\""))
3405 brightness_threshold,
3406 "Image darker than threshold (%d < %d): %s"
3407 % (brightness, brightness_threshold, image),
3417 test_completeness = {
3419 NS3UnusedSourcesTestCase,
3423 NS3CommonSettingsTestCase,
3424 NS3ConfigureBuildProfileTestCase,
3425 NS3ConfigureTestCase,
3426 NS3BuildBaseTestCase,
3427 NS3ExpectedUseTestCase,
3430 NS3UnusedSourcesTestCase,
3432 NS3CommonSettingsTestCase,
3433 NS3ConfigureBuildProfileTestCase,
3434 NS3ConfigureTestCase,
3435 NS3BuildBaseTestCase,
3436 NS3ExpectedUseTestCase,
3437 NS3QualityControlTestCase,
3440 NS3DependenciesTestCase,
3446 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3447 parser.add_argument(
3448 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3450 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3451 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3452 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3453 args = parser.parse_args(sys.argv[1:])
3455 loader = unittest.TestLoader()
3456 suite = unittest.TestSuite()
3459 for testCase
in test_completeness[args.completeness]:
3460 suite.addTests(loader.loadTestsFromTestCase(testCase))
3465 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3467 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3468 tests_to_remove = set(tests) - set(tests_to_run)
3469 for test_to_remove
in tests_to_remove:
3470 suite._tests.remove(tests[test_to_remove])
3473 if args.resume_from_test_name:
3475 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3476 keys =
list(tests.keys())
3478 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3479 suite._tests.remove(tests[keys[0]])
3483 ns3rc_script_bak = ns3rc_script +
".bak"
3484 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3485 shutil.move(ns3rc_script, ns3rc_script_bak)
3488 runner = unittest.TextTestRunner(failfast=
True, verbosity=1
if args.quiet
else 2)
3492 if os.path.exists(ns3rc_script_bak):
3493 shutil.move(ns3rc_script_bak, ns3rc_script)
3496 if __name__ ==
"__main__":
Python-on-whales wrapper for Docker-based ns-3 tests.
def __exit__(self, exc_type, exc_val, exc_tb)
Clean up the managed container at the end of the block "with DockerContainerManager() as container".
def __init__(self, unittest.TestCase currentTestCase, str containerName="ubuntu:latest")
Create and start container with containerName in the current ns-3 directory.
def __enter__(self)
Return the managed container when entiring the block "with DockerContainerManager() as container".
container
The Python-on-whales container instance.
Generic test case with basic function inherited by more complex tests.
def config_ok(self, return_code, stdout, stderr)
Check if configuration for release mode worked normally.
ns3_executables
ns3_executables holds a list of executables in .lock-ns3 # noqa
def setUp(self)
Clean configuration/build artifacts before testing configuration and build settings After configuring...
ns3_modules
ns3_modules holds a list to the modules enabled stored in .lock-ns3 # noqa
Tests ns3 regarding building the project.
def test_06_TestVersionFile(self)
Test if changing the version file affects the library names.
def test_10_AmbiguityCheck(self)
Test if ns3 can alert correctly in case a shortcut collision happens.
def test_01_BuildExistingTargets(self)
Try building the core library.
def test_12_CppyyBindings(self)
Test if we can use python bindings.
def test_08_InstallationAndUninstallation(self)
Tries setting a ns3 version, then installing it.
def test_11_StaticBuilds(self)
Test if we can build a static ns-3 library and link it to static programs.
def setUp(self)
Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned.
def test_02_BuildNonExistingTargets(self)
Try building core-test library without tests enabled.
def test_04_BuildProjectNoTaskLines(self)
Try hiding task lines.
def test_14_LinkContribModuleToSrcModule(self)
Test if we can link contrib modules to src modules.
def test_03_BuildProject(self)
Try building the project:
def test_13_FetchOptionalComponents(self)
Test if we had regressions with brite, click and openflow modules that depend on homonymous libraries...
def test_09_Scratches(self)
Tries to build scratch-simulator and subdir/scratch-simulator-subdir.
def test_05_BreakBuild(self)
Try removing an essential file to break the build.
ns3_executables
ns3_executables holds a list of executables in .lock-ns3 # noqa
def test_07_OutputDirectory(self)
Try setting a different output directory and if everything is in the right place and still working co...
ns3_libraries
ns3_libraries holds a list of built module libraries # noqa
ns3 tests related to generic options
def test_05_CheckVersion(self)
Test only passing 'show version' argument to ns3.
def setUp(self)
Clean configuration/build artifacts before common commands.
def test_01_NoOption(self)
Test not passing any arguments to.
def test_02_NoTaskLines(self)
Test only passing –quiet argument to ns3.
def test_03_CheckConfig(self)
Test only passing 'show config' argument to ns3.
def test_04_CheckProfile(self)
Test only passing 'show profile' argument to ns3.
ns-3 tests related to dependencies
def 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.
def test_10_DoxygenWithBuild(self)
Test the doxygen target that does trigger a full build.
def test_02_BuildAndRunExistingExecutableTarget(self)
Try to build and run test-runner.
def test_08_RunNoBuildGdb(self)
Test if scratch simulator is executed through gdb and lldb.
def test_05_RunNoBuildExistingExecutableTarget(self)
Try to run test-runner without building.
def test_06_RunNoBuildExistingLibraryTarget(self)
Test ns3 fails to run a library.
def test_03_BuildAndRunExistingLibraryTarget(self)
Try to build and run a library.
def test_01_BuildProject(self)
Try to build the project.
ns3_modules
ns3_modules holds a list to the modules enabled stored in .lock-ns3 # noqa
def test_14_EnableSudo(self)
Try to set ownership of scratch-simulator from current user to root, and change execution permissions...
def test_16_ForwardArgumentsToRunTargets(self)
Check if all flavors of different argument passing to executable targets are working.
def test_17_RunNoBuildLldb(self)
Test if scratch simulator is executed through lldb.
def test_15_CommandTemplate(self)
Check if command template is working.
def test_04_BuildAndRunNonExistingTarget(self)
Try to build and run an unknown target.
def test_07_RunNoBuildNonExistingExecutableTarget(self)
Test ns3 fails to run an unknown program.
def test_18_CpmAndVcpkgManagers(self)
Test if CPM and Vcpkg package managers are working properly.
ns3_executables
ns3_executables holds a list of executables in .lock-ns3 # noqa
def test_09_RunNoBuildValgrind(self)
Test if scratch simulator is executed through valgrind.
def test_13_Documentation(self)
Test the documentation target that builds both doxygen and sphinx based documentation.
def setUp(self)
Reuse cleaning/release configuration from NS3BaseTestCase if flag is cleaned Here examples,...
def test_11_DoxygenWithoutBuild(self)
Test the doxygen target that doesn't trigger a full build.
def test_12_SphinxDocumentation(self)
Test every individual target for Sphinx-based documentation.
ns-3 tests to control the quality of the repository over time, by checking the state of URLs listed a...
def test_03_CheckImageBrightness(self)
Check if images in the docs are above a brightness threshold.
def test_02_MemoryCheckWithSanitizers(self)
Test if all tests can be executed without hitting major memory bugs.
def 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 ...
def 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
dictionary directory_and_files
dictionary containing directories with .cc source files # noqa
def test_01_UnusedExampleSources(self)
Test if all example source files are being used in their respective CMakeLists.txt.
def setUp(self)
Scan all C++ source files and add them to a list based on their path.
def test_02_UnusedModuleSources(self)
Test if all module source files are being used in their respective CMakeLists.txt.
def test_03_UnusedUtilsSources(self)
Test if all utils source files are being used in their respective CMakeLists.txt.
def run_ns3(args, env=None, generator=platform_makefiles)
Runs the ns3 wrapper script with arguments.
def get_programs_list()
Extracts the programs list from .lock-ns3.
def get_libraries_list(lib_outdir=usual_lib_outdir)
Gets a list of built libraries.
def get_test_enabled()
Check if tests are enabled in the .lock-ns3.
def read_lock_entry(entry)
Read interesting entries from the .lock-ns3 file.
cmake_build_target_command
def get_headers_list(outdir=usual_outdir)
Gets a list of header files.
def 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,...
def get_enabled_modules()