21Test suite for the ns3 wrapper script
31from functools
import partial
34ns3_path = os.path.dirname(os.path.abspath(os.sep.join([__file__,
"../../"])))
35ns3_lock_filename = os.path.join(ns3_path,
".lock-ns3_%s_build" % sys.platform)
36ns3_script = os.sep.join([ns3_path,
"ns3"])
37ns3rc_script = os.sep.join([ns3_path,
".ns3rc"])
38usual_outdir = os.sep.join([ns3_path,
"build"])
39usual_lib_outdir = os.sep.join([usual_outdir,
"lib"])
45num_threads = max(1, os.cpu_count() - 1)
46cmake_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"))
49cmake_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")),
54win32 = sys.platform ==
"win32"
55platform_makefiles =
"MinGW Makefiles" if win32
else "Unix Makefiles"
56ext =
".exe" if win32
else ""
59def 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)
82def 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_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_ok(return_code, stdout, stderr)
865 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
868 self.
config_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_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_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_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_ok(return_code, stdout, stderr)
926 return_code, stdout, stderr =
run_ns3(
"configure -G \"{generator}\" --enable-modules=''")
927 self.
config_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_ok(return_code, stdout, stderr)
945 self.assertLess(len(enabled_modules), len(self.
ns3_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_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_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_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_ok(return_code, stdout, stderr)
993 self.assertLess(len(enabled_modules), len(self.
ns3_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_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.
type ==
"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.
type].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"))
1068 return_code, stdout, stderr =
run_ns3(
1069 'configure -G "{generator}" -d release --enable-verbose'
1071 self.
config_ok(return_code, stdout, stderr)
1076 self.assertIn(
"ns3-lte", enabled_modules)
1081 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1082 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
1085 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1086 self.
config_ok(return_code, stdout, stderr)
1091 self.assertIn(
"ns3-wifi", enabled_modules)
1096 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1098 ns3rc_template.format(
1099 modules=
"'core','network'", examples=
"True", tests=
"False"
1104 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1105 self.
config_ok(return_code, stdout, stderr)
1110 self.assertIn(
"ns3-core", enabled_modules)
1111 self.assertIn(
"ns3-network", enabled_modules)
1117 with open(ns3rc_script,
"w", encoding=
"utf-8")
as f:
1118 if ns3rc_type ==
"python":
1120 ns3rc_template.format(
1121 modules=
"""'core', #comment
1125 'network',
'internet',
'wimax'""",
1132 ns3rc_template.format(
1133 modules=
"'core', 'lte', 'network', 'internet', 'wimax'",
1139 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1140 self.
config_ok(return_code, stdout, stderr)
1145 self.assertIn(
"ns3-core", enabled_modules)
1146 self.assertIn(
"ns3-internet", enabled_modules)
1147 self.assertIn(
"ns3-lte", enabled_modules)
1148 self.assertIn(
"ns3-wimax", enabled_modules)
1153 os.remove(ns3rc_script)
1156 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1157 self.
config_ok(return_code, stdout, stderr)
1166 Test dry-run (printing commands to be executed instead of running them)
1172 for positional_command
in [
"configure",
"build",
"clean"]:
1173 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
1174 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
1176 self.assertEqual(return_code, return_code1)
1177 self.assertEqual(stdout, stdout1)
1178 self.assertEqual(stderr, stderr1)
1183 run_ns3(
'configure -G "{generator}" -d release --enable-verbose')
1184 run_ns3(
"build scratch-simulator")
1187 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
1188 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
1189 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
1190 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
1193 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
1194 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
1198 if "scratch-simulator" in program
and "subdir" not in program:
1199 scratch_path = program
1205 self.assertIn(scratch_path, stdout0)
1209 self.assertIn(
"Built target", stdout1)
1210 self.assertNotIn(scratch_path, stdout1)
1213 self.assertIn(
"The following commands would be executed:", stdout2)
1214 self.assertIn(scratch_path, stdout2)
1217 self.assertNotIn(
"Finished executing the following commands:", stdout3)
1218 self.assertNotIn(scratch_path, stdout3)
1222 Test if ns3
is propagating back the
return code
from the executables called
with the run command
1226 return_code, _, _ =
run_ns3(
"clean")
1227 self.assertEqual(return_code, 0)
1229 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-examples --enable-tests')
1230 self.assertEqual(return_code, 0)
1233 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
1234 self.assertEqual(return_code, 0)
1237 return_code, stdout, stderr =
run_ns3(
1238 'run "test-runner --test-name=command-line" --no-build'
1240 self.assertEqual(return_code, 0)
1243 return_code, stdout, stderr =
run_ns3(
1244 'run "test-runner --test-name=command-line" --no-build',
1245 env={
"NS_COMMANDLINE_INTROSPECTION":
".."},
1247 self.assertNotEqual(return_code, 0)
1250 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
1251 with open(sigsegv_example,
"w", encoding=
"utf-8")
as f:
1254 int main (int argc, char *argv[])
1256 char *s = "hello world"; *s =
'H';
1261 return_code, stdout, stderr = run_ns3("run sigsegv")
1263 self.assertEqual(return_code, 4294967295)
1264 self.assertIn(
"sigsegv-default.exe' returned non-zero exit status", stdout)
1266 self.assertEqual(return_code, 245)
1267 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
1270 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
1271 with open(abort_example,
"w", encoding=
"utf-8")
as f:
1276 using namespace ns3;
1277 int main (int argc, char *argv[])
1284 return_code, stdout, stderr = run_ns3("run abort")
1286 self.assertEqual(return_code, 3)
1287 self.assertIn(
"abort-default.exe' returned non-zero exit status", stdout)
1289 self.assertEqual(return_code, 250)
1290 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
1292 os.remove(sigsegv_example)
1293 os.remove(abort_example)
1297 Test passing 'show config' argument to ns3 to get the configuration table
1300 return_code, stdout, stderr = run_ns3("show config")
1301 self.assertEqual(return_code, 0)
1302 self.assertIn(
"Summary of ns-3 settings", stdout)
1306 Test passing 'show profile' argument to ns3 to get the build profile
1309 return_code, stdout, stderr = run_ns3("show profile")
1310 self.assertEqual(return_code, 0)
1311 self.assertIn(
"Build profile: release", stdout)
1315 Test passing 'show version' argument to ns3 to get the build version
1318 if shutil.which(
"git")
is None:
1319 self.skipTest(
"git is not available")
1321 return_code, _, _ =
run_ns3(
'configure -G "{generator}" --enable-build-version')
1322 self.assertEqual(return_code, 0)
1324 return_code, stdout, stderr =
run_ns3(
"show version")
1325 self.assertEqual(return_code, 0)
1326 self.assertIn(
"ns-3 version:", stdout)
1330 Test if CMake target names
for scratches
and ns3 shortcuts
1331 are working correctly
1338 "scratch/subdir1/main.cc",
1339 "scratch/subdir2/main.cc",
1340 "scratch/main.test.dots.in.name.cc",
1342 backup_files = [
"scratch/.main.cc"]
1345 for path
in test_files + backup_files:
1346 filepath = os.path.join(ns3_path, path)
1347 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
1348 with open(filepath,
"w", encoding=
"utf-8")
as f:
1350 f.write(
"int main (int argc, char *argv[]){}")
1358 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1359 self.assertEqual(return_code, 0)
1362 for path
in test_files + backup_files:
1363 path = path.replace(
".cc",
"")
1366 "--build . --target %s -j %d" % (path.replace(
"/",
"_"), num_threads),
1367 cwd=os.path.join(ns3_path,
"cmake-cache"),
1369 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
1370 if "main" in path
and ".main" not in path:
1371 self.assertEqual(return_code1, 0)
1372 self.assertEqual(return_code2, 0)
1374 self.assertEqual(return_code1, 2)
1375 self.assertEqual(return_code2, 1)
1378 for path
in test_files:
1379 path = path.replace(
".cc",
"")
1380 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
1382 self.assertEqual(return_code, 0)
1384 self.assertEqual(return_code, 1)
1388 container.execute(
"apt-get update")
1389 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
1392 "./ns3 configure --enable-modules=core,network,internet -- -DCMAKE_CXX_COMPILER=/usr/bin/g++"
1394 except DockerException
as e:
1396 for path
in test_files:
1397 path = path.replace(
".cc",
"")
1399 container.execute(f
"./ns3 run {path}")
1400 except DockerException
as e:
1406 for path
in test_files + backup_files:
1407 source_absolute_path = os.path.join(ns3_path, path)
1408 os.remove(source_absolute_path)
1409 if "empty" in path
or ".main" in path:
1411 filename = os.path.basename(path).replace(
".cc",
"")
1412 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
1413 if os.path.exists(executable_absolute_path):
1414 executable_name =
list(
1415 filter(
lambda x: filename
in x, os.listdir(executable_absolute_path))
1418 os.remove(os.path.join(executable_absolute_path, executable_name))
1419 if not os.listdir(os.path.dirname(path)):
1420 os.rmdir(os.path.dirname(source_absolute_path))
1422 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}"')
1423 self.assertEqual(return_code, 0)
1427 Test if ns3
is inserting additional arguments by MPICH
and OpenMPI to run on the CI
1431 if shutil.which(
"mpiexec")
is None or win32:
1432 self.skipTest(
"Mpi is not available")
1434 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --enable-examples')
1435 self.assertEqual(return_code, 0)
1439 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
1440 self.assertEqual(return_code, 0)
1443 sample_simulator_path =
list(filter(
lambda x:
"sample-simulator" in x, executables))[0]
1445 mpi_command =
'--dry-run run sample-simulator --command-template="mpiexec -np 2 %s"'
1446 non_mpi_command =
'--dry-run run sample-simulator --command-template="echo %s"'
1449 return_code, stdout, stderr =
run_ns3(mpi_command)
1450 self.assertEqual(return_code, 0)
1451 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1454 return_code, stdout, stderr =
run_ns3(mpi_command)
1455 self.assertEqual(return_code, 0)
1456 if os.getenv(
"USER",
"") ==
"root":
1457 if shutil.which(
"ompi_info"):
1459 "mpiexec --allow-run-as-root --oversubscribe -np 2 %s" % sample_simulator_path,
1464 "mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout
1467 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
1470 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1471 self.assertEqual(return_code, 0)
1472 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1475 return_code, stdout, stderr =
run_ns3(non_mpi_command)
1476 self.assertEqual(return_code, 0)
1477 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
1479 return_code, stdout, stderr =
run_ns3(
'configure -G "{generator}" --disable-examples')
1480 self.assertEqual(return_code, 0)
1484 Test if CMake
and ns3 fail
in the expected ways when:
1485 - examples
from modules
or general examples fail
if they depend on a
1486 library
with a name shorter than 4 characters
or are disabled when
1487 a library
is nonexistent
1488 - a module library passes the configuration but fails to build due to
1492 os.makedirs("contrib/borked", exist_ok=
True)
1493 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
1496 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1498 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1499 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1504 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1505 LIBRARIES_TO_LINK ${libcore} %s
1508 % invalid_or_nonexistent_library
1511 return_code, stdout, stderr = run_ns3('configure -G "{generator}" --enable-examples')
1512 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1513 self.assertEqual(return_code, 0)
1514 elif invalid_or_nonexistent_library
in [
"lib"]:
1515 self.assertEqual(return_code, 1)
1516 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1520 return_code, stdout, stderr =
run_ns3(
"build borked")
1521 if invalid_or_nonexistent_library
in [
""]:
1522 self.assertEqual(return_code, 0)
1523 elif invalid_or_nonexistent_library
in [
"lib"]:
1524 self.assertEqual(return_code, 2)
1525 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1526 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1527 self.assertEqual(return_code, 2)
1528 if "lld" in stdout + stderr:
1530 "unable to find library -l%s" % invalid_or_nonexistent_library, stderr
1532 elif "mold" in stdout + stderr:
1533 self.assertIn(
"library not found: %s" % invalid_or_nonexistent_library, stderr)
1535 self.assertIn(
"cannot find -l%s" % invalid_or_nonexistent_library, stderr)
1543 with open(
"contrib/borked/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1548 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1549 LIBRARIES_TO_LINK ${libcore}
1553 for invalid_or_nonexistent_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1554 with open(
"contrib/borked/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1559 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1560 LIBRARIES_TO_LINK ${libborked} %s
1563 % invalid_or_nonexistent_library
1566 return_code, stdout, stderr = run_ns3('configure -G "{generator}"')
1567 if invalid_or_nonexistent_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1568 self.assertEqual(return_code, 0)
1569 elif invalid_or_nonexistent_library
in [
"lib"]:
1570 self.assertEqual(return_code, 1)
1571 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1575 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1576 if invalid_or_nonexistent_library
in [
""]:
1577 self.assertEqual(return_code, 0)
1578 elif invalid_or_nonexistent_library
in [
"libf"]:
1579 self.assertEqual(return_code, 2)
1580 self.assertIn(
"Invalid library name: %s" % invalid_or_nonexistent_library, stderr)
1581 elif invalid_or_nonexistent_library
in [
"gsd",
"libfi",
"calibre"]:
1582 self.assertEqual(return_code, 1)
1583 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1587 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1591 Test if CMake can properly handle modules containing
"lib",
1592 which
is used internally
as a prefix
for module libraries
1596 os.makedirs("contrib/calibre", exist_ok=
True)
1597 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1600 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1602 with open(
"contrib/calibre/CMakeLists.txt",
"w", encoding=
"utf-8")
as f:
1607 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1608 LIBRARIES_TO_LINK ${libcore}
1613 return_code, stdout, stderr = run_ns3('configure -G "{generator}"')
1616 self.assertEqual(return_code, 0)
1619 self.assertIn(
"calibre", stdout)
1623 self.assertNotIn(
"care", stdout)
1625 os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc"))
1629 return_code, stdout, stderr =
run_ns3(
"build calibre")
1630 self.assertEqual(return_code, 0)
1633 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1637 Test if CMake performance tracing works
and produces the
1638 cmake_performance_trace.log file
1641 cmake_performance_trace_log = os.path.join(ns3_path, "cmake_performance_trace.log")
1642 if os.path.exists(cmake_performance_trace_log):
1643 os.remove(cmake_performance_trace_log)
1645 return_code, stdout, stderr =
run_ns3(
"configure --trace-performance")
1646 self.assertEqual(return_code, 0)
1648 self.assertIn(
"--profiling-format=google-trace --profiling-output=", stdout)
1651 "--profiling-format=google-trace --profiling-output=./cmake_performance_trace.log",
1654 self.assertTrue(os.path.exists(cmake_performance_trace_log))
1658 Check if ENABLE_BUILD_VERSION
and version.cache are working
1666 container.execute(
"apt-get update")
1667 container.execute(
"apt-get install -y python3 ninja-build cmake g++")
1670 container.execute(
"./ns3 clean")
1673 version_cache_file = os.path.join(ns3_path,
"src/core/model/version.cache")
1676 if os.path.exists(version_cache_file):
1677 os.remove(version_cache_file)
1681 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1682 except DockerException:
1684 self.assertFalse(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1687 version_cache_contents = (
1688 "CLOSEST_TAG = '\"ns-3.0.0\"'\n"
1689 "VERSION_COMMIT_HASH = '\"0000000000\"'\n"
1690 "VERSION_DIRTY_FLAG = '0'\n"
1691 "VERSION_MAJOR = '3'\n"
1692 "VERSION_MINOR = '0'\n"
1693 "VERSION_PATCH = '0'\n"
1694 "VERSION_RELEASE_CANDIDATE = '\"\"'\n"
1695 "VERSION_TAG = '\"ns-3.0.0\"'\n"
1696 "VERSION_TAG_DISTANCE = '0'\n"
1697 "VERSION_BUILD_PROFILE = 'debug'\n"
1699 with open(version_cache_file,
"w", encoding=
"utf-8")
as version:
1700 version.write(version_cache_contents)
1703 container.execute(
"./ns3 clean")
1704 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1705 container.execute(
"./ns3 build core")
1706 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1709 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1710 self.assertEqual(version.read(), version_cache_contents)
1715 os.rename(os.path.join(ns3_path,
".git"), os.path.join(ns3_path,
"temp_git"))
1717 container.execute(
"apt-get install -y git")
1718 container.execute(
"./ns3 clean")
1719 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1720 container.execute(
"./ns3 build core")
1721 except DockerException:
1723 os.rename(os.path.join(ns3_path,
"temp_git"), os.path.join(ns3_path,
".git"))
1724 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1727 container.execute(
"./ns3 clean")
1728 container.execute(
"./ns3 configure -G Ninja --enable-build-version")
1729 container.execute(
"./ns3 build core")
1730 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1731 with open(version_cache_file,
"r", encoding=
"utf-8")
as version:
1732 self.assertNotEqual(version.read(), version_cache_contents)
1735 if os.path.exists(version_cache_file):
1736 os.remove(version_cache_file)
1740 Test filtering in examples
and tests
from specific modules
1744 return_code, stdout, stderr =
run_ns3(
1745 'configure -G "{generator}" --enable-examples --enable-tests'
1747 self.
config_ok(return_code, stdout, stderr)
1752 return_code, stdout, stderr =
run_ns3(
1753 "configure -G \"{generator}\" --filter-module-examples-and-tests='core;network'"
1755 self.
config_ok(return_code, stdout, stderr)
1761 self.assertEqual(len(modules_after_filtering), len(modules_before_filtering))
1763 self.assertLess(len(programs_after_filtering), len(programs_before_filtering))
1766 return_code, stdout, stderr =
run_ns3(
1767 "configure -G \"{generator}\" --filter-module-examples-and-tests='core'"
1769 self.
config_ok(return_code, stdout, stderr)
1777 return_code, stdout, stderr =
run_ns3(
1778 "configure -G \"{generator}\" --disable-examples --disable-tests --filter-module-examples-and-tests=''"
1780 self.
config_ok(return_code, stdout, stderr)
1788 Check if fast linkers LLD
and Mold are correctly found
and configured
1795 container.execute(
"apt-get update")
1796 container.execute(
"apt-get install -y python3 ninja-build cmake g++ lld")
1799 container.execute(
"./ns3 configure -G Ninja")
1802 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1804 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1806 self.assertIn(
"-fuse-ld=lld", f.read())
1810 container.execute(
"./ns3 build core")
1811 except DockerException:
1812 self.assertTrue(
False,
"Build with lld failed")
1815 if not os.path.exists(
"./mold-1.4.2-x86_64-linux.tar.gz"):
1817 "wget https://github.com/rui314/mold/releases/download/v1.4.2/mold-1.4.2-x86_64-linux.tar.gz"
1820 "tar xzfC mold-1.4.2-x86_64-linux.tar.gz /usr/local --strip-components=1"
1825 container.execute(
"./ns3 configure -G Ninja")
1828 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1830 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1832 self.assertIn(
"-fuse-ld=mold", f.read())
1836 container.execute(
"./ns3 build core")
1837 except DockerException:
1838 self.assertTrue(
False,
"Build with mold failed")
1841 os.remove(
"./mold-1.4.2-x86_64-linux.tar.gz")
1844 container.execute(
"./ns3 configure -G Ninja -- -DNS3_FAST_LINKERS=OFF")
1847 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"build.ninja")))
1849 os.path.join(ns3_path,
"cmake-cache",
"build.ninja"),
"r", encoding=
"utf-8"
1851 self.assertNotIn(
"-fuse-ld=mold", f.read())
1855 Check if NS3_CLANG_TIMETRACE feature
is working
1856 Clang
's -ftime-trace plus ClangAnalyzer report
1862 container.execute(
"apt-get update")
1863 container.execute(
"apt-get install -y python3 ninja-build cmake clang-10")
1868 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DNS3_CLANG_TIMETRACE=ON"
1870 except DockerException
as e:
1871 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1873 container.execute(
"apt-get install -y git")
1878 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DNS3_CLANG_TIMETRACE=ON"
1880 except DockerException
as e:
1881 self.assertIn(
"could not find git for clone of ClangBuildAnalyzer", e.stderr)
1884 time_trace_report_path = os.path.join(ns3_path,
"ClangBuildAnalyzerReport.txt")
1885 if os.path.exists(time_trace_report_path):
1886 os.remove(time_trace_report_path)
1890 container.execute(
"./ns3 build timeTraceReport")
1891 except DockerException
as e:
1892 self.assertTrue(
False,
"Failed to build the ClangAnalyzer's time trace report")
1895 self.assertTrue(os.path.exists(time_trace_report_path))
1899 container.execute(
"apt-get install -y g++")
1900 container.execute(
"apt-get remove -y clang-10")
1904 "./ns3 configure -G Ninja --enable-modules=core --enable-examples --enable-tests -- -DNS3_CLANG_TIMETRACE=ON"
1907 False,
"ClangTimeTrace requires Clang, but GCC just passed the checks too"
1909 except DockerException
as e:
1910 self.assertIn(
"TimeTrace is a Clang feature", e.stderr)
1914 Check if NS3_NINJA_TRACE feature
is working
1915 Ninja
's .ninja_log conversion to about://tracing
1916 json format conversion with Ninjatracing
1922 container.execute(
"apt-get update")
1923 container.execute(
"apt-get install -y python3 cmake clang-10")
1928 "./ns3 configure --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10"
1930 except DockerException
as e:
1931 self.assertIn(
"Ninjatracing requires the Ninja generator", e.stderr)
1936 container.execute(
"apt-get install -y ninja-build")
1940 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10"
1942 except DockerException
as e:
1943 self.assertIn(
"could not find git for clone of NinjaTracing", e.stderr)
1945 container.execute(
"apt-get install -y git")
1949 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10"
1951 except DockerException
as e:
1952 self.assertTrue(
False,
"Failed to configure with Ninjatracing")
1955 ninja_trace_path = os.path.join(ns3_path,
"ninja_performance_trace.json")
1956 if os.path.exists(ninja_trace_path):
1957 os.remove(ninja_trace_path)
1960 container.execute(
"./ns3 build core")
1964 container.execute(
"./ns3 build ninjaTrace")
1965 except DockerException
as e:
1966 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1969 self.assertTrue(os.path.exists(ninja_trace_path))
1970 trace_size = os.stat(ninja_trace_path).st_size
1971 os.remove(ninja_trace_path)
1978 "./ns3 configure -G Ninja --enable-modules=core --enable-ninja-tracing -- -DCMAKE_CXX_COMPILER=/usr/bin/clang++-10 -DNS3_CLANG_TIMETRACE=ON"
1980 except DockerException
as e:
1981 self.assertTrue(
False,
"Failed to configure Ninjatracing with Clang's TimeTrace")
1984 container.execute(
"./ns3 build core")
1988 container.execute(
"./ns3 build ninjaTrace")
1989 except DockerException
as e:
1990 self.assertTrue(
False,
"Failed to run Ninjatracing's tool to build the trace")
1992 self.assertTrue(os.path.exists(ninja_trace_path))
1993 timetrace_size = os.stat(ninja_trace_path).st_size
1994 os.remove(ninja_trace_path)
1997 self.assertGreater(timetrace_size, trace_size)
2001 Check if precompiled headers are being enabled correctly.
2011 container.execute(
"apt-get update")
2012 container.execute(
"apt-get install -y python3 cmake ccache g++")
2014 container.execute(
"./ns3 configure")
2015 except DockerException
as e:
2016 self.assertIn(
"incompatible with ccache", e.stderr)
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 libcore", 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))
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))
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:
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 libcore)
2340 target_link_libraries(test PRIVATE ns3::libcore)
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(
"A required package was 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)
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
2525 return_code, stdout, stderr =
run_ns3(
2526 'configure -G "{generator}" --enable-examples --disable-gtk --enable-static'
2532 self.assertEqual(return_code, 1)
2533 self.assertIn(
"Static builds are unsupported on Windows", stderr)
2536 self.assertEqual(return_code, 0)
2539 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
2540 self.assertEqual(return_code, 0)
2541 self.assertIn(
"Built target", stdout)
2547 Test if we can use python bindings
2552 except ModuleNotFoundError:
2553 self.skipTest(
"Cppyy was not found")
2556 return_code, stdout, stderr =
run_ns3(
2557 'configure -G "{generator}" --enable-examples --enable-python-bindings'
2561 self.assertEqual(return_code, 0)
2564 return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
2565 self.assertEqual(return_code, 0)
2568 return_code, stdout, stderr =
run_program(
"test.py",
"-p mixed-wired-wireless", python=
True)
2569 self.assertEqual(return_code, 0)
2573 "test.py",
"-p ./examples/wireless/mixed-wired-wireless", python=
True
2575 self.assertEqual(return_code, 0)
2579 Test if we had regressions
with brite, click
and openflow modules
2580 that depend on homonymous libraries
2583 if shutil.which(
"git")
is None:
2584 self.skipTest(
"Missing git")
2587 return_code, stdout, stderr =
run_ns3(
"configure -- -DNS3_FETCH_OPTIONAL_COMPONENTS=ON")
2588 self.assertEqual(return_code, 0)
2592 return_code, stdout, stderr =
run_ns3(
"build brite click openflow")
2593 self.assertEqual(return_code, 0)
2597 Test if we can link contrib modules to src modules
2600 if shutil.which(
"git")
is None:
2601 self.skipTest(
"Missing git")
2603 destination_contrib = os.path.join(ns3_path,
"contrib/test-contrib-dependency")
2604 destination_src = os.path.join(ns3_path,
"src/test-src-dependent-on-contrib")
2606 if os.path.exists(destination_contrib):
2607 shutil.rmtree(destination_contrib)
2608 if os.path.exists(destination_src):
2609 shutil.rmtree(destination_src)
2613 os.path.join(ns3_path,
"build-support/test-files/test-contrib-dependency"),
2614 destination_contrib,
2617 os.path.join(ns3_path,
"build-support/test-files/test-src-dependent-on-contrib"),
2622 return_code, stdout, stderr =
run_ns3(
"configure --enable-examples")
2623 self.assertEqual(return_code, 0)
2626 return_code, stdout, stderr =
run_ns3(
"run source-example")
2627 self.assertEqual(return_code, 0)
2630 shutil.rmtree(destination_contrib)
2631 shutil.rmtree(destination_src)
2636 Tests ns3 usage in more realistic scenarios
2641 Reuse cleaning/release configuration from NS3BaseTestCase
if flag
is cleaned
2642 Here examples, tests
and documentation are also enabled.
2649 return_code, stdout, stderr =
run_ns3(
2650 'configure -d release -G "{generator}" --enable-examples --enable-tests'
2652 self.
config_ok(return_code, stdout, stderr)
2655 self.assertTrue(os.path.exists(ns3_lock_filename))
2661 self.assertTrue(os.path.exists(ns3_lock_filename))
2668 Try to build the project
2671 return_code, stdout, stderr = run_ns3("build")
2672 self.assertEqual(return_code, 0)
2673 self.assertIn(
"Built target", stdout)
2675 self.assertTrue(os.path.exists(program))
2678 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
2679 self.assertIn(cmake_build_project_command, stdout)
2683 Try to build and run test-runner
2686 return_code, stdout, stderr = run_ns3('run "test-runner --list" --verbose')
2687 self.assertEqual(return_code, 0)
2688 self.assertIn(
"Built target test-runner", stdout)
2693 Try to build and run a library
2696 return_code, stdout, stderr = run_ns3("run core")
2697 self.assertEqual(return_code, 1)
2698 self.assertIn(
"Couldn't find the specified program: core", stderr)
2702 Try to build and run an unknown target
2705 return_code, stdout, stderr = run_ns3("run nonsense")
2706 self.assertEqual(return_code, 1)
2707 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2711 Try to run test-runner without building
2714 return_code, stdout, stderr = run_ns3("build test-runner")
2715 self.assertEqual(return_code, 0)
2717 return_code, stdout, stderr =
run_ns3(
'run "test-runner --list" --no-build --verbose')
2718 self.assertEqual(return_code, 0)
2719 self.assertNotIn(
"Built target test-runner", stdout)
2724 Test ns3 fails to run a library
2727 return_code, stdout, stderr = run_ns3("run core --no-build")
2728 self.assertEqual(return_code, 1)
2729 self.assertIn(
"Couldn't find the specified program: core", stderr)
2733 Test ns3 fails to run an unknown program
2736 return_code, stdout, stderr = run_ns3("run nonsense --no-build")
2737 self.assertEqual(return_code, 1)
2738 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
2742 Test if scratch simulator
is executed through gdb
and lldb
2745 if shutil.which(
"gdb")
is None:
2746 self.skipTest(
"Missing gdb")
2748 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2749 self.assertEqual(return_code, 0)
2751 return_code, stdout, stderr =
run_ns3(
2752 "run scratch-simulator --gdb --verbose --no-build", env={
"gdb_eval":
"1"}
2754 self.assertEqual(return_code, 0)
2755 self.assertIn(
"scratch-simulator", stdout)
2757 self.assertIn(
"GNU gdb", stdout)
2759 self.assertIn(
"No debugging symbols found", stdout)
2763 Test if scratch simulator
is executed through valgrind
2766 if shutil.which(
"valgrind")
is None:
2767 self.skipTest(
"Missing valgrind")
2769 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
2770 self.assertEqual(return_code, 0)
2772 return_code, stdout, stderr =
run_ns3(
2773 "run scratch-simulator --valgrind --verbose --no-build"
2775 self.assertEqual(return_code, 0)
2776 self.assertIn(
"scratch-simulator", stderr)
2777 self.assertIn(
"Memcheck", stderr)
2781 Test the doxygen target that does trigger a full build
2784 if shutil.which(
"doxygen")
is None:
2785 self.skipTest(
"Missing doxygen")
2787 if shutil.which(
"bash")
is None:
2788 self.skipTest(
"Missing bash")
2790 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2792 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
2793 for filename
in doxygen_files:
2794 file_path = os.sep.join([doc_folder, filename])
2795 if os.path.exists(file_path):
2796 os.remove(file_path)
2803 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
2804 self.assertEqual(return_code, 0)
2806 self.assertIn(
"Built target doxygen", stdout)
2810 Test the doxygen target that doesn't trigger a full build
2813 if shutil.which(
"doxygen")
is None:
2814 self.skipTest(
"Missing doxygen")
2822 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
2823 self.assertEqual(return_code, 0)
2825 self.assertIn(
"Built target doxygen-no-build", stdout)
2829 Test every individual target for Sphinx-based documentation
2832 if shutil.which(
"sphinx-build")
is None:
2833 self.skipTest(
"Missing sphinx")
2835 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2838 for target
in [
"installation",
"contributing",
"manual",
"models",
"tutorial"]:
2840 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2841 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
2842 if os.path.exists(doc_build_folder):
2843 shutil.rmtree(doc_build_folder)
2844 if os.path.exists(doc_temp_folder):
2845 shutil.rmtree(doc_temp_folder)
2848 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
2849 self.assertEqual(return_code, 0, target)
2851 self.assertIn(
"Built target sphinx_%s" % target, stdout)
2854 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2855 self.assertTrue(os.path.exists(doc_build_folder))
2858 for build_type
in [
"latex",
"html",
"singlehtml"]:
2859 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
2863 Test the documentation target that builds
2864 both doxygen and sphinx based documentation
2867 if shutil.which(
"doxygen")
is None:
2868 self.skipTest(
"Missing doxygen")
2869 if shutil.which(
"sphinx-build")
is None:
2870 self.skipTest(
"Missing sphinx")
2872 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
2881 for target
in [
"manual",
"models",
"tutorial"]:
2882 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
2883 if os.path.exists(doc_build_folder):
2884 shutil.rmtree(doc_build_folder)
2886 return_code, stdout, stderr =
run_ns3(
"docs all")
2887 self.assertEqual(return_code, 0)
2889 self.assertIn(
"Built target sphinx", stdout)
2891 self.assertIn(
"Built target doxygen", stdout)
2895 Try to set ownership of scratch-simulator from current user to root,
2896 and change execution permissions
2901 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
2904 if sudo_password
is None:
2905 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
2908 self.assertFalse(enable_sudo
is True)
2911 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator")
2912 self.assertEqual(return_code, 0)
2913 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2915 scratch_simulator_path =
list(
2918 prev_fstat = os.stat(scratch_simulator_path)
2921 return_code, stdout, stderr =
run_ns3(
2922 "run scratch-simulator --enable-sudo", env={
"SUDO_PASSWORD": sudo_password}
2924 self.assertEqual(return_code, 0)
2925 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
2927 fstat = os.stat(scratch_simulator_path)
2933 likely_fuse_mount = (
2934 (prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID)
2935 )
and prev_fstat.st_uid == 0
2937 if win32
or likely_fuse_mount:
2938 self.skipTest(
"Windows or likely a FUSE mount")
2941 self.assertEqual(fstat.st_uid, 0)
2943 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2947 return_code, stdout, stderr =
run_ns3(
"configure --enable-sudo")
2948 self.assertEqual(return_code, 0)
2952 self.assertTrue(enable_sudo)
2956 if os.path.exists(executable):
2957 os.remove(executable)
2960 return_code, stdout, stderr =
run_ns3(
"build", env={
"SUDO_PASSWORD": sudo_password})
2961 self.assertEqual(return_code, 0)
2964 self.assertIn(
"chown root", stdout)
2965 self.assertIn(
"chmod u+s", stdout)
2967 self.assertIn(os.path.basename(executable), stdout)
2970 fstat = os.stat(scratch_simulator_path)
2971 self.assertEqual(fstat.st_uid, 0)
2973 fstat.st_mode & stat.S_ISUID, stat.S_ISUID
2978 Check if command template
is working
2983 return_code0, stdout0, stderr0 =
run_ns3(
"run sample-simulator --command-template")
2984 self.assertEqual(return_code0, 2)
2985 self.assertIn(
"argument --command-template: expected one argument", stderr0)
2987 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
2988 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
2989 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
2990 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
2991 for stderr
in [stderr1, stderr2, stderr3]:
2992 self.assertIn(
"not all arguments converted during string formatting", stderr)
2995 return_code4, stdout4, _ =
run_ns3(
2996 'run sample-simulator --command-template "%s --PrintVersion" --verbose'
2998 return_code5, stdout5, _ =
run_ns3(
2999 'run sample-simulator --command-template="%s --PrintVersion" --verbose'
3001 self.assertEqual((return_code4, return_code5), (0, 0))
3003 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout4)
3004 self.assertIn(
"sample-simulator{ext} --PrintVersion".format(ext=ext), stdout5)
3008 Check if all flavors of different argument passing to
3009 executable targets are working
3014 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
3015 return_code1, stdout1, stderr1 =
run_ns3(
3016 'run sample-simulator --command-template="%s --help" --verbose'
3018 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --verbose -- --help")
3020 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3021 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout0)
3022 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout1)
3023 self.assertIn(
"sample-simulator{ext} --help".format(ext=ext), stdout2)
3026 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
3027 return_code1, stdout1, stderr1 =
run_ns3(
3028 'run sample-simulator --command-template="%s --help" --no-build'
3030 return_code2, stdout2, stderr2 =
run_ns3(
"run sample-simulator --no-build -- --help")
3031 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3032 self.assertEqual(stdout0, stdout1)
3033 self.assertEqual(stdout1, stdout2)
3034 self.assertEqual(stderr0, stderr1)
3035 self.assertEqual(stderr1, stderr2)
3038 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
3039 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
3040 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
3042 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
3043 self.assertIn(
"sample-simulator{ext} --PrintGlobals".format(ext=ext), stdout0)
3044 self.assertIn(
"sample-simulator{ext} --PrintGroups".format(ext=ext), stdout1)
3045 self.assertIn(
"sample-simulator{ext} --PrintTypeIds".format(ext=ext), stdout2)
3048 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
3049 return_code, stdout, stderr =
run_ns3(cmd)
3050 self.assertEqual(return_code, 0)
3056 "sample-simulator{ext} --PrintGroups --PrintGlobals --PrintTypeIds".format(ext=ext),
3061 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
3062 cmd1 =
"run sample-simulator --PrintTypeIds"
3064 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
3065 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
3066 self.assertEqual((return_code0, return_code1), (1, 1))
3067 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
3068 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
3072 Test if scratch simulator
is executed through lldb
3075 if shutil.which(
"lldb")
is None:
3076 self.skipTest(
"Missing lldb")
3078 return_code, stdout, stderr =
run_ns3(
"build scratch-simulator")
3079 self.assertEqual(return_code, 0)
3081 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
3082 self.assertEqual(return_code, 0)
3083 self.assertIn(
"scratch-simulator", stdout)
3084 self.assertIn(
"(lldb) target create", stdout)
3088 Test if CPM
and Vcpkg package managers are working properly
3092 return_code, stdout, stderr =
run_ns3(
"clean")
3093 self.assertEqual(return_code, 0)
3096 if os.path.exists(
"vcpkg"):
3097 shutil.rmtree(
"vcpkg")
3100 destination_src = os.path.join(ns3_path,
"src/test-package-managers")
3102 if os.path.exists(destination_src):
3103 shutil.rmtree(destination_src)
3107 os.path.join(ns3_path,
"build-support/test-files/test-package-managers"),
3113 container.execute(
"apt-get update")
3114 container.execute(
"apt-get install -y python3 cmake g++ ninja-build")
3119 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=ON")
3120 self.skipTest(
"Armadillo is already installed")
3121 except DockerException
as e:
3125 return_code, stdout, stderr =
run_ns3(
"clean")
3126 self.assertEqual(return_code, 0)
3129 container.execute(
"apt-get install -y git")
3134 "./ns3 configure -- -DNS3_CPM=ON -DTEST_PACKAGE_MANAGER:STRING=CPM"
3136 except DockerException
as e:
3141 container.execute(
"./ns3 build test-package-managers")
3142 except DockerException
as e:
3146 return_code, stdout, stderr =
run_ns3(
"clean")
3147 self.assertEqual(return_code, 0)
3150 container.execute(
"apt-get install -y zip unzip tar curl")
3153 container.execute(
"apt-get install -y pkg-config gfortran")
3157 container.execute(
"./ns3 configure -- -DNS3_VCPKG=ON")
3158 except DockerException
as e:
3163 container.execute(
"./ns3 configure -- -DTEST_PACKAGE_MANAGER:STRING=VCPKG")
3164 except DockerException
as e:
3169 container.execute(
"./ns3 build test-package-managers")
3170 except DockerException
as e:
3174 if os.path.exists(destination_src):
3175 shutil.rmtree(destination_src)
3180 ns-3 tests to control the quality of the repository over time,
3181 by checking the state of URLs listed and more
3186 Test if all urls
in source files are alive
3195 self.skipTest(
"Django URL validators are not available")
3202 urllib3.disable_warnings()
3205 self.skipTest(
"Requests library is not available")
3207 regex = re.compile(
r"((http|https)://[^\ \n\)\"\'\}><\]\;\`\\]*)")
3210 whitelisted_urls = {
3211 "https://gitlab.com/your-user-name/ns-3-dev",
3212 "https://www.nsnam.org/release/ns-allinone-3.31.rc1.tar.bz2",
3213 "https://www.nsnam.org/release/ns-allinone-3.X.rcX.tar.bz2",
3214 "https://www.nsnam.org/releases/ns-3-x",
3215 "https://www.nsnam.org/releases/ns-allinone-3.(x-1",
3216 "https://www.nsnam.org/releases/ns-allinone-3.x.tar.bz2",
3217 "https://ns-buildmaster.ee.washington.edu:8010/",
3219 "https://cmake.org/cmake/help/latest/manual/cmake-",
3220 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_",
3222 "http://www.lysator.liu.se/~alla/dia/",
3224 "http://www.ieeeghn.org/wiki/index.php/First-Hand:Digital_Television:_The_Digital_Terrestrial_Television_Broadcasting_(DTTB",
3225 "http://en.wikipedia.org/wiki/Namespace_(computer_science",
3226 "http://en.wikipedia.org/wiki/Bonobo_(component_model",
3227 "http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85",
3229 "http://www.research.att.com/info/kpv/",
3230 "http://www.research.att.com/~gsf/",
3231 "http://nsnam.isi.edu/nsnam/index.php/Contributed_Code",
3232 "http://scan5.coverity.com/cgi-bin/upload.py",
3234 "https://github.com/Kitware/CMake/releases/download/v3.27.1/cmake-3.27.1-linux-x86_64.tar.gz-",
3235 "http://mirrors.kernel.org/fedora/releases/11/Everything/i386/os/Packages/",
3239 files_and_urls = set()
3241 for topdir
in [
"bindings",
"doc",
"examples",
"src",
"utils"]:
3242 for root, dirs, files
in os.walk(topdir):
3244 if "build" in root
or "_static" in root
or "source-temp" in root
or "html" in root:
3247 filepath = os.path.join(root, file)
3250 if not os.path.isfile(filepath):
3254 if file.endswith(
".svg"):
3258 with open(filepath,
"r", encoding=
"utf-8")
as f:
3259 matches = regex.findall(f.read())
3265 map(
lambda x: x[0][:-1]
if x[0][-1]
in ".," else x[0], matches)
3267 except UnicodeDecodeError:
3268 skipped_files.append(filepath)
3272 for url
in set(urls) - unique_urls - whitelisted_urls:
3273 unique_urls.add(url)
3274 files_and_urls.add((filepath, url))
3277 from django.core.exceptions
import ValidationError
3278 from django.core.validators
import URLValidator
3280 validate_url = URLValidator()
3284 "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"
3288 def test_file_url(args):
3289 test_filepath, test_url = args
3290 dead_link_msg =
None
3294 validate_url(test_url)
3295 except ValidationError:
3296 dead_link_msg =
"%s: URL %s, invalid URL" % (test_filepath, test_url)
3297 except Exception
as e:
3298 self.assertEqual(
False,
True, msg=e.__str__())
3300 if dead_link_msg
is not None:
3301 return dead_link_msg
3309 response = requests.get(test_url, verify=
False, headers=headers, timeout=50)
3312 if response.status_code
in [200, 301]:
3313 dead_link_msg =
None
3318 if response.status_code
in [302, 308, 500, 503]:
3319 if response.reason.lower()
in [
3321 "moved temporarily",
3322 "permanent redirect",
3324 "service temporarily unavailable",
3326 dead_link_msg =
None
3330 dead_link_msg =
"%s: URL %s: returned code %d" % (
3333 response.status_code,
3335 except requests.exceptions.InvalidURL:
3336 dead_link_msg =
"%s: URL %s: invalid URL" % (test_filepath, test_url)
3337 except requests.exceptions.SSLError:
3338 dead_link_msg =
"%s: URL %s: SSL error" % (test_filepath, test_url)
3339 except requests.exceptions.TooManyRedirects:
3340 dead_link_msg =
"%s: URL %s: too many redirects" % (test_filepath, test_url)
3341 except Exception
as e:
3343 error_msg = e.args[0].reason.__str__()
3344 except AttributeError:
3345 error_msg = e.args[0]
3346 dead_link_msg =
"%s: URL %s: failed with exception: %s" % (
3352 return dead_link_msg
3355 from concurrent.futures
import ThreadPoolExecutor
3357 with ThreadPoolExecutor(max_workers=100)
as executor:
3358 dead_links =
list(executor.map(test_file_url,
list(files_and_urls)))
3361 dead_links =
list(sorted(filter(
lambda x: x
is not None, dead_links)))
3362 self.assertEqual(len(dead_links), 0, msg=
"\n".join([
"Dead links found:", *dead_links]))
3366 Test if all tests can be executed without hitting major memory bugs
3369 return_code, stdout, stderr = run_ns3(
3370 "configure --enable-tests --enable-examples --enable-sanitizers -d optimized"
3372 self.assertEqual(return_code, 0)
3374 test_return_code, stdout, stderr =
run_program(
"test.py",
"", python=
True)
3375 self.assertEqual(test_return_code, 0)
3379 Check if images
in the docs are above a brightness threshold.
3380 This should prevent screenshots
with dark UI themes.
3383 if shutil.which(
"convert")
is None:
3384 self.skipTest(
"Imagemagick was not found")
3386 from pathlib
import Path
3389 image_extensions = [
"png",
"jpg"]
3391 for extension
in image_extensions:
3392 images +=
list(Path(
"./doc").glob(
"**/figures/*.{ext}".format(ext=extension)))
3393 images +=
list(Path(
"./doc").glob(
"**/figures/**/*.{ext}".format(ext=extension)))
3396 imagemagick_get_image_brightness =
'convert {image} -colorspace HSI -channel b -separate +channel -scale 1x1 -format "%[fx:100*u]" info:'
3400 brightness_threshold = 50
3401 for image
in images:
3402 brightness = subprocess.check_output(
3403 imagemagick_get_image_brightness.format(image=image).split()
3405 brightness = float(brightness.decode().strip(
"'\""))
3408 brightness_threshold,
3409 "Image darker than threshold (%d < %d): %s"
3410 % (brightness, brightness_threshold, image),
3420 test_completeness = {
3422 NS3UnusedSourcesTestCase,
3426 NS3CommonSettingsTestCase,
3427 NS3ConfigureBuildProfileTestCase,
3428 NS3ConfigureTestCase,
3429 NS3BuildBaseTestCase,
3430 NS3ExpectedUseTestCase,
3433 NS3UnusedSourcesTestCase,
3435 NS3CommonSettingsTestCase,
3436 NS3ConfigureBuildProfileTestCase,
3437 NS3ConfigureTestCase,
3438 NS3BuildBaseTestCase,
3439 NS3ExpectedUseTestCase,
3440 NS3QualityControlTestCase,
3443 NS3DependenciesTestCase,
3449 parser = argparse.ArgumentParser(
"Test suite for the ns-3 buildsystem")
3450 parser.add_argument(
3451 "-c",
"--completeness", choices=test_completeness.keys(), default=
"complete"
3453 parser.add_argument(
"-tn",
"--test-name", action=
"store", default=
None, type=str)
3454 parser.add_argument(
"-rtn",
"--resume-from-test-name", action=
"store", default=
None, type=str)
3455 parser.add_argument(
"-q",
"--quiet", action=
"store_true", default=
False)
3456 args = parser.parse_args(sys.argv[1:])
3458 loader = unittest.TestLoader()
3459 suite = unittest.TestSuite()
3462 for testCase
in test_completeness[args.completeness]:
3463 suite.addTests(loader.loadTestsFromTestCase(testCase))
3468 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3470 tests_to_run = set(map(
lambda x: x
if args.test_name
in x
else None, tests.keys()))
3471 tests_to_remove = set(tests) - set(tests_to_run)
3472 for test_to_remove
in tests_to_remove:
3473 suite._tests.remove(tests[test_to_remove])
3476 if args.resume_from_test_name:
3478 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
3479 keys =
list(tests.keys())
3481 while args.resume_from_test_name
not in keys[0]
and len(tests) > 0:
3482 suite._tests.remove(tests[keys[0]])
3486 ns3rc_script_bak = ns3rc_script +
".bak"
3487 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
3488 shutil.move(ns3rc_script, ns3rc_script_bak)
3491 runner = unittest.TextTestRunner(failfast=
True, verbosity=1
if args.quiet
else 2)
3495 if os.path.exists(ns3rc_script_bak):
3496 shutil.move(ns3rc_script_bak, ns3rc_script)
3499if __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
dict 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.
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
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.
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()
partial cmake_build_target_command