22Test suite for the ns3 wrapper script
32from functools
import partial
35ns3_path = os.path.dirname(os.path.abspath(os.sep.join([__file__,
"../../"])))
36ns3_lock_filename = os.path.join(ns3_path,
".lock-ns3_%s_build" % sys.platform)
37ns3_script = os.sep.join([ns3_path,
"ns3"])
38ns3rc_script = os.sep.join([ns3_path,
".ns3rc"])
39usual_outdir = os.sep.join([ns3_path,
"build"])
40usual_lib_outdir = os.sep.join([usual_outdir,
"lib"])
46cmake_build_project_command =
"cmake --build . -j".format(ns3_path=ns3_path)
47cmake_build_target_command = partial(
"cmake --build . -j {jobs} --target {target}".format,
48 jobs=
max(1, os.cpu_count() - 1)
54 Runs the ns3 wrapper script with arguments
55 @param args: string containing arguments that will get split before calling ns3
56 @param env: environment variables dictionary
57 @return tuple containing (error code, stdout
and stderr)
60 possible_leftovers = [
"contrib/borked",
"contrib/calibre"]
61 for leftover
in possible_leftovers:
62 if os.path.exists(leftover):
63 shutil.rmtree(leftover, ignore_errors=
True)
64 return run_program(ns3_script, args, python=
True, env=env)
68def run_program(program, args, python=False, cwd=ns3_path, env=None):
70 Runs a program with the given arguments
and returns a tuple containing (error code, stdout
and stderr)
71 @param program: program to execute (
or python script)
72 @param args: string containing arguments that will get split before calling the program
73 @param python: flag indicating whether the program
is a python script
74 @param cwd: the working directory used that will be the root folder
for the execution
75 @param env: environment variables dictionary
76 @return tuple containing (error code, stdout
and stderr)
79 raise Exception(
"args should be a string")
83 arguments = [sys.executable, program]
88 arguments.extend(re.findall(
"(?:\".*?\"|\S)+", args))
90 for i
in range(len(arguments)):
91 arguments[i] = arguments[i].replace(
"\"",
"")
94 current_env = os.environ.copy()
98 current_env.update(env)
101 ret = subprocess.run(
103 stdin=subprocess.DEVNULL,
104 stdout=subprocess.PIPE,
105 stderr=subprocess.PIPE,
110 return ret.returncode, ret.stdout.decode(sys.stdout.encoding), ret.stderr.decode(sys.stderr.encoding)
115 Extracts the programs list from .lock-ns3
116 @return list of programs.
119 with open(ns3_lock_filename)
as f:
120 exec(f.read(), globals(), values)
121 return values[
"ns3_runnable_programs"]
126 Gets a list of built libraries
127 @param lib_outdir: path containing libraries
128 @return list of built libraries.
130 return glob.glob(lib_outdir +
'/*', recursive=
True)
135 Gets a list of header files
136 @param outdir: path containing headers
137 @return list of headers.
139 return glob.glob(outdir +
'/**/*.h', recursive=
True)
144 Read interesting entries from the .lock-ns3 file
145 @param entry: entry to read
from .lock-ns3
146 @return value of the requested entry.
149 with open(ns3_lock_filename)
as f:
150 exec(f.read(), globals(), values)
151 return values.get(entry,
None)
156 Check if tests are enabled
in the .lock-ns3
164 Check if tests are enabled
in the .lock-ns3
165 @return list of enabled modules (prefixed
with 'ns3-').
172 ns-3 tests related to checking if source files were left behind,
not being used by CMake
176 directory_and_files = {}
180 Scan all C++ source files and add them to a list based on their path
183 for root, dirs, files
in os.walk(ns3_path):
184 if "gitlab-ci-local" in root:
187 if name.endswith(
".cc"):
188 path = os.path.join(root, name)
189 directory = os.path.dirname(path)
196 Test if all example source files are being used
in their respective CMakeLists.txt
199 unused_sources = set()
202 if os.sep +
"examples" not in example_directory:
206 with open(os.path.join(example_directory,
"CMakeLists.txt"),
"r")
as f:
207 cmake_contents = f.read()
212 if os.path.basename(file).replace(
".cc",
"")
not in cmake_contents:
213 unused_sources.add(file)
215 self.assertListEqual([],
list(unused_sources))
219 Test if all module source files are being used
in their respective CMakeLists.txt
222 unused_sources = set()
225 is_not_module =
not (
"src" in directory
or "contrib" in directory)
226 is_example = os.sep +
"examples" in directory
227 is_bindings = os.sep +
"bindings" in directory
229 if is_not_module
or is_bindings
or is_example:
234 cmake_path = os.path.join(directory,
"CMakeLists.txt")
235 while not os.path.exists(cmake_path):
236 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
237 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
240 with open(cmake_path,
"r")
as f:
241 cmake_contents = f.read()
245 if os.path.basename(file)
not in cmake_contents:
246 unused_sources.add(file)
249 exceptions = [
"win32-system-wall-clock-ms.cc",
251 for exception
in exceptions:
252 for unused_source
in unused_sources:
253 if os.path.basename(unused_source) == exception:
254 unused_sources.remove(unused_source)
257 self.assertListEqual([],
list(unused_sources))
261 Test if all utils source files are being used
in their respective CMakeLists.txt
264 unused_sources = set()
267 is_module =
"src" in directory
or "contrib" in directory
268 if os.sep +
"utils" not in directory
or is_module:
273 cmake_path = os.path.join(directory,
"CMakeLists.txt")
274 while not os.path.exists(cmake_path):
275 parent_directory = os.path.dirname(os.path.dirname(cmake_path))
276 cmake_path = os.path.join(parent_directory, os.path.basename(cmake_path))
279 with open(cmake_path,
"r")
as f:
280 cmake_contents = f.read()
284 if os.path.basename(file)
not in cmake_contents:
285 unused_sources.add(file)
287 self.assertListEqual([],
list(unused_sources))
292 ns3 tests related to generic options
297 Clean configuration/build artifacts before common commands
306 Test not passing any arguments to
309 return_code, stdout, stderr = run_ns3("")
310 self.assertEqual(return_code, 1)
311 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
315 Test only passing --quiet argument to ns3
318 return_code, stdout, stderr = run_ns3("--quiet")
319 self.assertEqual(return_code, 1)
320 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
324 Test only passing 'show config' argument to ns3
327 return_code, stdout, stderr = run_ns3("show config")
328 self.assertEqual(return_code, 1)
329 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
333 Test only passing 'show profile' argument to ns3
336 return_code, stdout, stderr = run_ns3("show profile")
337 self.assertEqual(return_code, 1)
338 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
342 Test only passing 'show version' argument to ns3
345 return_code, stdout, stderr = run_ns3("show version")
346 self.assertEqual(return_code, 1)
347 self.assertIn(
"You need to configure ns-3 first: try ./ns3 configure", stdout)
352 ns3 tests related to build profiles
357 Clean configuration/build artifacts before testing configuration settings
369 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" -d debug --enable-verbose")
370 self.assertEqual(return_code, 0)
371 self.assertIn(
"Build profile : debug", stdout)
372 self.assertIn(
"Build files have been written to", stdout)
375 return_code, stdout, stderr =
run_ns3(
"build core")
376 self.assertEqual(return_code, 0)
377 self.assertIn(
"Built target libcore", stdout)
380 self.assertGreater(len(libraries), 0)
381 self.assertIn(
"core-debug", libraries[0])
385 Test the release build
388 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" -d release")
389 self.assertEqual(return_code, 0)
390 self.assertIn(
"Build profile : release", stdout)
391 self.assertIn(
"Build files have been written to", stdout)
395 Test the optimized build
398 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" -d optimized --enable-verbose")
399 self.assertEqual(return_code, 0)
400 self.assertIn(
"Build profile : optimized", stdout)
401 self.assertIn(
"Build files have been written to", stdout)
404 return_code, stdout, stderr =
run_ns3(
"build core")
405 self.assertEqual(return_code, 0)
406 self.assertIn(
"Built target libcore", stdout)
409 self.assertGreater(len(libraries), 0)
410 self.assertIn(
"core-optimized", libraries[0])
414 Test a build type with a typo
417 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" -d Optimized")
418 self.assertEqual(return_code, 2)
419 self.assertIn(
"invalid choice: 'Optimized'", stderr)
423 Test a build type with another typo
426 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" -d OPTIMIZED")
427 self.assertEqual(return_code, 2)
428 self.assertIn(
"invalid choice: 'OPTIMIZED'", stderr)
433 Generic test case with basic function inherited by more complex tests.
441 Check if configuration
for release mode worked normally
442 @param return_code:
return code
from CMake
443 @param stdout: output
from CMake.
446 self.assertEqual(return_code, 0)
447 self.assertIn("Build profile : release", stdout)
448 self.assertIn(
"Build files have been written to", stdout)
452 Clean configuration/build artifacts before testing configuration and build settings
453 After configuring the build
as release,
454 check
if configuration worked
and check expected output files.
459 if os.path.exists(ns3rc_script):
460 os.remove(ns3rc_script)
463 if not NS3BaseTestCase.cleaned_once:
464 NS3BaseTestCase.cleaned_once =
True
466 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" -d release --enable-verbose")
470 self.assertTrue(os.path.exists(ns3_lock_filename))
475 self.assertTrue(os.path.exists(ns3_lock_filename))
482 Test ns3 configuration options
490 Reuse cleaning/release configuration from NS3BaseTestCase
if flag
is cleaned
493 if not NS3ConfigureTestCase.cleaned_once:
494 NS3ConfigureTestCase.cleaned_once =
True
495 NS3BaseTestCase.cleaned_once =
False
500 Test enabling and disabling examples
503 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" --enable-examples")
512 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-examples")
522 Test enabling and disabling tests
526 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-tests")
530 return_code, stdout, stderr =
run_ns3(
"build core-test")
533 self.assertEqual(return_code, 0)
534 self.assertIn(
"Built target libcore-test", stdout)
537 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-tests")
541 return_code, stdout, stderr =
run_ns3(
"build core-test")
544 self.assertEqual(return_code, 1)
545 self.assertIn(
"Target to build does not exist: core-test", stdout)
549 Test enabling specific modules
553 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-modules='network;wifi'")
559 self.assertIn(
"ns3-network", enabled_modules)
560 self.assertIn(
"ns3-wifi", enabled_modules)
563 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-modules='core' --enable-python-bindings")
568 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-modules='' --disable-python-bindings")
576 Test disabling specific modules
580 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-modules='lte;wimax'")
585 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
586 self.assertNotIn(
"ns3-lte", enabled_modules)
587 self.assertNotIn(
"ns3-wimax", enabled_modules)
590 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-modules=''")
598 Test enabling comma-separated (waf-style) examples
602 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-modules='network,wifi'")
608 self.assertIn(
"ns3-network", enabled_modules)
609 self.assertIn(
"ns3-wifi", enabled_modules)
612 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-modules=''")
620 Test disabling comma-separated (waf-style) examples
624 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-modules='lte,mpi'")
629 self.assertLess(len(enabled_modules), len(self.
ns3_modules))
630 self.assertNotIn(
"ns3-lte", enabled_modules)
631 self.assertNotIn(
"ns3-mpi", enabled_modules)
634 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-modules=''")
642 Test loading settings from the ns3rc config file
645 ns3rc_template = "# ! /usr/bin/env python\
647 # A list of the modules that will be enabled when ns-3 is run.\
648 # Modules that depend on the listed modules will be enabled also.\
650 # All modules can be enabled by choosing 'all_modules'.\
651 modules_enabled = [{modules}]\
653 # Set this equal to true if you want examples to be run.\
654 examples_enabled = {examples}\
656 # Set this equal to true if you want tests to be run.\
657 tests_enabled = {tests}\
661 with open(ns3rc_script,
"w")
as f:
662 f.write(ns3rc_template.format(modules=
"'lte'", examples=
"False", tests=
"True"))
665 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
671 self.assertIn(
"ns3-lte", enabled_modules)
676 with open(ns3rc_script,
"w")
as f:
677 f.write(ns3rc_template.format(modules=
"'wifi'", examples=
"True", tests=
"False"))
680 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
686 self.assertIn(
"ns3-wifi", enabled_modules)
691 os.remove(ns3rc_script)
694 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
704 Test dry-run (printing commands to be executed instead of running them)
710 for positional_command
in [
"configure",
"build",
"clean"]:
711 return_code, stdout, stderr =
run_ns3(
"--dry-run %s" % positional_command)
712 return_code1, stdout1, stderr1 =
run_ns3(
"%s --dry-run" % positional_command)
714 self.assertEqual(return_code, return_code1)
715 self.assertEqual(stdout, stdout1)
716 self.assertEqual(stderr, stderr1)
721 run_ns3(
"configure -G \"Unix Makefiles\" -d release --enable-verbose")
722 run_ns3(
"build scratch-simulator")
725 return_code0, stdout0, stderr0 =
run_ns3(
"--dry-run run scratch-simulator")
726 return_code1, stdout1, stderr1 =
run_ns3(
"run scratch-simulator")
727 return_code2, stdout2, stderr2 =
run_ns3(
"--dry-run run scratch-simulator --no-build")
728 return_code3, stdout3, stderr3 =
run_ns3(
"run scratch-simulator --no-build")
731 self.assertEqual(sum([return_code0, return_code1, return_code2, return_code3]), 0)
732 self.assertEqual([stderr0, stderr1, stderr2, stderr3], [
""] * 4)
736 if "scratch-simulator" in program
and "subdir" not in program:
737 scratch_path = program
743 self.assertIn(scratch_path, stdout0)
747 self.assertIn(
"Built target", stdout1)
748 self.assertNotIn(scratch_path, stdout1)
751 self.assertIn(
"The following commands would be executed:", stdout2)
752 self.assertIn(scratch_path, stdout2)
755 self.assertNotIn(
"Finished executing the following commands:", stdout3)
756 self.assertNotIn(scratch_path, stdout3)
760 Test if ns3
is propagating back the
return code
from the executables called
with the run command
764 return_code, _, _ =
run_ns3(
"clean")
765 self.assertEqual(return_code, 0)
767 return_code, _, _ =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-examples --enable-tests")
768 self.assertEqual(return_code, 0)
771 return_code, stdout, stderr =
run_ns3(
"build command-line-example test-runner")
772 self.assertEqual(return_code, 0)
775 return_code, stdout, stderr =
run_ns3(
"run \"test-runner --test-name=command-line\" --no-build")
776 self.assertEqual(return_code, 0)
779 return_code, stdout, stderr =
run_ns3(
"run \"test-runner --test-name=command-line\" --no-build",
780 env={
"NS_COMMANDLINE_INTROSPECTION":
".."}
782 self.assertNotEqual(return_code, 0)
785 sigsegv_example = os.path.join(ns3_path,
"scratch",
"sigsegv.cc")
786 with open(sigsegv_example,
"w")
as f:
788 int main (int argc, char *argv[])
790 char *s = "hello world"; *s =
'H';
794 return_code, stdout, stderr = run_ns3("run sigsegv")
795 self.assertEqual(return_code, 245)
796 self.assertIn(
"sigsegv-default' died with <Signals.SIGSEGV: 11>", stdout)
799 abort_example = os.path.join(ns3_path,
"scratch",
"abort.cc")
800 with open(abort_example,
"w")
as f:
805 int main (int argc, char *argv[])
811 return_code, stdout, stderr = run_ns3("run abort")
812 self.assertEqual(return_code, 250)
813 self.assertIn(
"abort-default' died with <Signals.SIGABRT: 6>", stdout)
815 os.remove(sigsegv_example)
816 os.remove(abort_example)
820 Test passing 'show config' argument to ns3 to get the configuration table
823 return_code, stdout, stderr = run_ns3("show config")
824 self.assertEqual(return_code, 0)
825 self.assertIn(
"Summary of optional NS-3 features", stdout)
829 Test passing 'show profile' argument to ns3 to get the build profile
832 return_code, stdout, stderr = run_ns3("show profile")
833 self.assertEqual(return_code, 0)
834 self.assertIn(
"Build profile: default", stdout)
838 Test passing 'show version' argument to ns3 to get the build version
841 return_code, _, _ = run_ns3("configure -G \"Unix Makefiles\" --enable-build-version")
842 self.assertEqual(return_code, 0)
844 return_code, stdout, stderr =
run_ns3(
"show version")
845 self.assertEqual(return_code, 0)
846 self.assertIn(
"ns-3 version:", stdout)
850 Test if CMake target names
for scratches
and ns3 shortcuts
851 are working correctly
855 test_files = ["scratch/main.cc",
857 "scratch/subdir1/main.cc",
858 "scratch/subdir2/main.cc"]
861 for path
in test_files:
862 filepath = os.path.join(ns3_path, path)
863 os.makedirs(os.path.dirname(filepath), exist_ok=
True)
864 with open(filepath,
"w")
as f:
866 f.write(
"int main (int argc, char *argv[]){}")
874 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
875 self.assertEqual(return_code, 0)
878 for path
in test_files:
879 path = path.replace(
".cc",
"")
880 return_code1, stdout1, stderr1 =
run_program(
"cmake",
"--build . --target %s"
881 % path.replace(
"/",
"_"),
882 cwd=os.path.join(ns3_path,
"cmake-cache"))
883 return_code2, stdout2, stderr2 =
run_ns3(
"build %s" % path)
885 self.assertEqual(return_code1, 0)
886 self.assertEqual(return_code2, 0)
888 self.assertEqual(return_code1, 2)
889 self.assertEqual(return_code2, 1)
892 for path
in test_files:
893 path = path.replace(
".cc",
"")
894 return_code, stdout, stderr =
run_ns3(
"run %s --no-build" % path)
896 self.assertEqual(return_code, 0)
898 self.assertEqual(return_code, 1)
901 for path
in test_files:
902 source_absolute_path = os.path.join(ns3_path, path)
903 os.remove(source_absolute_path)
906 filename = os.path.basename(path).replace(
".cc",
"")
907 executable_absolute_path = os.path.dirname(os.path.join(ns3_path,
"build", path))
908 executable_name =
list(filter(
lambda x: filename
in x,
909 os.listdir(executable_absolute_path)
913 os.remove(os.path.join(executable_absolute_path, executable_name))
914 if path
not in [
"scratch/main.cc",
"scratch/empty.cc"]:
915 os.rmdir(os.path.dirname(source_absolute_path))
917 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
918 self.assertEqual(return_code, 0)
922 Test if ns3
is inserting additional arguments by MPICH
and OpenMPI to run on the CI
926 if shutil.which(
"mpiexec")
is None:
930 return_code, stdout, stderr =
run_ns3(
"build sample-simulator")
931 self.assertEqual(return_code, 0)
934 sample_simulator_path =
list(filter(
lambda x:
"sample-simulator" in x, self.
ns3_executables))[0]
936 mpi_command =
"--dry-run run sample-simulator --command-template=\"mpiexec -np 2 %s\""
937 non_mpi_command =
"--dry-run run sample-simulator --command-template=\"echo %s\""
940 return_code, stdout, stderr =
run_ns3(mpi_command)
941 self.assertEqual(return_code, 0)
942 self.assertIn(
"mpiexec -np 2 %s" % sample_simulator_path, stdout)
945 return_code, stdout, stderr =
run_ns3(mpi_command, env={
"MPI_CI":
"1"})
946 self.assertEqual(return_code, 0)
947 if shutil.which(
"ompi_info"):
948 self.assertIn(
"mpiexec --allow-run-as-root --oversubscribe -np 2 %s" % sample_simulator_path, stdout)
950 self.assertIn(
"mpiexec --allow-run-as-root -np 2 %s" % sample_simulator_path, stdout)
953 return_code, stdout, stderr =
run_ns3(non_mpi_command)
954 self.assertEqual(return_code, 0)
955 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
958 return_code, stdout, stderr =
run_ns3(non_mpi_command, env={
"MPI_CI":
"1"})
959 self.assertEqual(return_code, 0)
960 self.assertIn(
"echo %s" % sample_simulator_path, stdout)
964 Test if CMake
and ns3 fail
in the expected ways when:
965 - examples
from modules
or general examples fail
if they depend on a
966 library
with a name shorter than 4 characters
or are disabled when
967 a library
is non-existant
968 - a module library passes the configuration but fails to build due to
972 os.makedirs("contrib/borked", exist_ok=
True)
973 os.makedirs(
"contrib/borked/examples", exist_ok=
True)
976 with open(
"contrib/borked/examples/CMakeLists.txt",
"w")
as f:
978 for invalid_or_non_existant_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
979 with open(
"contrib/borked/CMakeLists.txt",
"w")
as f:
983 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
984 LIBRARIES_TO_LINK ${libcore} %s
986 """ % invalid_or_non_existant_library)
988 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\" --enable-examples")
989 if invalid_or_non_existant_library
in [
"",
"gsd",
"libfi",
"calibre"]:
990 self.assertEqual(return_code, 0)
991 elif invalid_or_non_existant_library
in [
"lib"]:
992 self.assertEqual(return_code, 1)
993 self.assertIn(
"Invalid library name: %s" % invalid_or_non_existant_library, stderr)
997 return_code, stdout, stderr =
run_ns3(
"build borked")
998 if invalid_or_non_existant_library
in [
""]:
999 self.assertEqual(return_code, 0)
1000 elif invalid_or_non_existant_library
in [
"lib"]:
1001 self.assertEqual(return_code, 2)
1002 self.assertIn(
"Invalid library name: %s" % invalid_or_non_existant_library, stderr)
1003 elif invalid_or_non_existant_library
in [
"gsd",
"libfi",
"calibre"]:
1004 self.assertEqual(return_code, 2)
1005 self.assertIn(
"cannot find -l%s" % invalid_or_non_existant_library, stderr)
1013 with open(
"contrib/borked/CMakeLists.txt",
"w")
as f:
1017 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1018 LIBRARIES_TO_LINK ${libcore}
1021 for invalid_or_non_existant_library
in [
"",
"gsd",
"lib",
"libfi",
"calibre"]:
1022 with open(
"contrib/borked/examples/CMakeLists.txt",
"w")
as f:
1026 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc
1027 LIBRARIES_TO_LINK ${libborked} %s
1029 """ % invalid_or_non_existant_library)
1031 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\"")
1032 if invalid_or_non_existant_library
in [
"",
"gsd",
"libfi",
"calibre"]:
1033 self.assertEqual(return_code, 0)
1034 elif invalid_or_non_existant_library
in [
"lib"]:
1035 self.assertEqual(return_code, 1)
1036 self.assertIn(
"Invalid library name: %s" % invalid_or_non_existant_library, stderr)
1040 return_code, stdout, stderr =
run_ns3(
"build borked-example")
1041 if invalid_or_non_existant_library
in [
""]:
1042 self.assertEqual(return_code, 0)
1043 elif invalid_or_non_existant_library
in [
"libf"]:
1044 self.assertEqual(return_code, 2)
1045 self.assertIn(
"Invalid library name: %s" % invalid_or_non_existant_library, stderr)
1046 elif invalid_or_non_existant_library
in [
"gsd",
"libfi",
"calibre"]:
1047 self.assertEqual(return_code, 1)
1048 self.assertIn(
"Target to build does not exist: borked-example", stdout)
1052 shutil.rmtree(
"contrib/borked", ignore_errors=
True)
1056 Test if CMake can properly handle modules containing
"lib",
1057 which
is used internally
as a prefix
for module libraries
1061 os.makedirs("contrib/calibre", exist_ok=
True)
1062 os.makedirs(
"contrib/calibre/examples", exist_ok=
True)
1065 with open(
"contrib/calibre/examples/CMakeLists.txt",
"w")
as f:
1067 with open(
"contrib/calibre/CMakeLists.txt",
"w")
as f:
1071 SOURCE_FILES ${PROJECT_SOURCE_DIR}/build-support/empty.cc
1072 LIBRARIES_TO_LINK ${libcore}
1076 return_code, stdout, stderr = run_ns3("configure -G \"Unix Makefiles\"")
1079 self.assertEqual(return_code, 0)
1082 self.assertIn(
"calibre", stdout)
1086 self.assertNotIn(
"care", stdout)
1087 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake-cache",
"pkgconfig",
"ns3-calibre.pc")))
1090 return_code, stdout, stderr =
run_ns3(
"build calibre")
1091 self.assertEqual(return_code, 0)
1094 shutil.rmtree(
"contrib/calibre", ignore_errors=
True)
1098 Test if CMake performance tracing works
and produces the
1099 cmake_performance_trace.log file
1102 return_code, stdout, stderr = run_ns3("configure --trace-performance")
1103 self.assertEqual(return_code, 0)
1104 self.assertIn(
"--profiling-format=google-trace --profiling-output=../cmake_performance_trace.log", stdout)
1105 self.assertTrue(os.path.exists(os.path.join(ns3_path,
"cmake_performance_trace.log")))
1110 Tests ns3 regarding building the project
1114 cleaned_once = False
1118 Reuse cleaning/release configuration from NS3BaseTestCase
if flag
is cleaned
1121 if not NS3BuildBaseTestCase.cleaned_once:
1122 NS3BuildBaseTestCase.cleaned_once =
True
1123 NS3BaseTestCase.cleaned_once =
False
1130 Try building the core library
1133 return_code, stdout, stderr = run_ns3("build core")
1134 self.assertEqual(return_code, 0)
1135 self.assertIn(
"Built target libcore", stdout)
1139 Try building core-test library without tests enabled
1143 return_code, stdout, stderr =
run_ns3(
"build core-test")
1144 self.assertEqual(return_code, 1)
1145 self.assertIn(
"Target to build does not exist: core-test", stdout)
1149 Try building the project:
1152 return_code, stdout, stderr = run_ns3("build")
1153 self.assertEqual(return_code, 0)
1154 self.assertIn(
"Built target", stdout)
1156 self.assertTrue(os.path.exists(program))
1157 self.assertIn(cmake_build_project_command, stdout)
1161 Try hiding task lines
1164 return_code, stdout, stderr = run_ns3("--quiet build")
1165 self.assertEqual(return_code, 0)
1166 self.assertIn(cmake_build_project_command, stdout)
1170 Try removing an essential file to break the build
1174 attribute_cc_path = os.sep.join([ns3_path,
"src",
"core",
"model",
"attribute.cc"])
1175 attribute_cc_bak_path = attribute_cc_path +
".bak"
1176 shutil.move(attribute_cc_path, attribute_cc_bak_path)
1179 return_code, stdout, stderr =
run_ns3(
"build")
1180 self.assertNotEqual(return_code, 0)
1183 shutil.move(attribute_cc_bak_path, attribute_cc_path)
1186 return_code, stdout, stderr =
run_ns3(
"build")
1187 self.assertEqual(return_code, 0)
1191 Test if changing the version file affects the library names
1194 version_file = os.sep.join([ns3_path, "VERSION"])
1195 with open(version_file,
"w")
as f:
1199 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
1203 return_code, stdout, stderr =
run_ns3(
"build")
1204 self.assertEqual(return_code, 0)
1205 self.assertIn(
"Built target", stdout)
1211 for program
in new_programs:
1212 self.assertTrue(os.path.exists(program))
1220 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
1221 for library
in new_libraries:
1222 self.assertNotIn(
"libns3-dev", library)
1223 self.assertIn(
"libns3-00", library)
1224 self.assertTrue(os.path.exists(library))
1227 with open(version_file,
"w")
as f:
1231 NS3BuildBaseTestCase.cleaned_once =
False
1235 Try setting a different output directory and if everything
is
1236 in the right place
and still working correctly
1255 absolute_path = os.sep.join([ns3_path,
"build",
"release"])
1256 relative_path = os.sep.join([
"build",
"release"])
1257 for different_out_dir
in [absolute_path, relative_path]:
1258 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --out=%s" % different_out_dir)
1260 self.assertIn(
"Build directory : %s" % absolute_path, stdout)
1268 for program
in new_programs:
1269 self.assertTrue(os.path.exists(program))
1274 self.assertEqual(len(new_libraries), len(self.
ns3_libraries))
1275 for library
in new_libraries:
1276 self.assertTrue(os.path.exists(library))
1279 shutil.rmtree(absolute_path)
1282 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --out=''")
1284 self.assertIn(
"Build directory : %s" % usual_outdir, stdout)
1292 for program
in new_programs:
1293 self.assertTrue(os.path.exists(program))
1298 for library
in libraries:
1299 self.assertTrue(os.path.exists(library))
1303 Tries setting a ns3 version, then installing it.
1304 After that, tries searching for ns-3
with CMake
's find_package(ns3).
1305 Finally, tries using core library in a 3rd-party project
1310 for library
in libraries:
1314 version_file = os.sep.join([ns3_path,
"VERSION"])
1315 with open(version_file,
"w")
as f:
1319 install_prefix = os.sep.join([ns3_path,
"build",
"install"])
1320 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --prefix=%s" % install_prefix)
1332 lib64 = os.path.exists(os.sep.join([install_prefix,
"lib64"]))
1333 installed_libdir = os.sep.join([install_prefix, (
"lib64" if lib64
else "lib")])
1337 installed_libraries_list =
";".join(installed_libraries)
1338 for library
in libraries:
1339 library_name = os.path.basename(library)
1340 self.assertIn(library_name, installed_libraries_list)
1344 missing_headers =
list(set([os.path.basename(x)
for x
in headers])
1345 - (set([os.path.basename(x)
for x
in installed_headers]))
1347 self.assertEqual(len(missing_headers), 0)
1350 test_main_file = os.sep.join([install_prefix,
"main.cpp"])
1351 with open(test_main_file,
"w")
as f:
1354 using namespace ns3;
1357 Simulator::Stop (Seconds (1.0));
1359 Simulator::Destroy ();
1367 for version
in [
"",
"3.01",
"3.00"]:
1368 find_package_import =
"""
1369 list(APPEND CMAKE_PREFIX_PATH ./{lib}/cmake/ns3)
1370 find_package(ns3 {version} COMPONENTS libcore)
1371 target_link_libraries(test PRIVATE ns3::libcore)
1372 """.format(lib=("lib64" if lib64 else "lib"), version=version)
1373 pkgconfig_import = """
1374 list(APPEND CMAKE_PREFIX_PATH ./)
1375 include(FindPkgConfig)
1376 pkg_check_modules(ns3 REQUIRED IMPORTED_TARGET ns3-core{version})
1377 target_link_libraries(test PUBLIC PkgConfig::ns3)
1378 """.format(lib=("lib64" if lib64 else "lib"),
1379 version="=" + version
if version
else ""
1382 for import_type
in [pkgconfig_import, find_package_import]:
1383 test_cmake_project =
"""
1384 cmake_minimum_required(VERSION 3.10..3.10)
1386 add_executable(test main.cpp)
1389 test_cmake_project_file = os.sep.join([install_prefix, "CMakeLists.txt"])
1390 with open(test_cmake_project_file,
"w")
as f:
1391 f.write(test_cmake_project)
1394 cmake = shutil.which(
"cmake")
1396 "-DCMAKE_BUILD_TYPE=debug .",
1398 if version ==
"3.00":
1399 self.assertEqual(return_code, 1)
1400 if import_type == find_package_import:
1401 self.assertIn(
'Could not find a configuration file for package "ns3" that is compatible',
1402 stderr.replace(
"\n",
""))
1403 elif import_type == pkgconfig_import:
1404 self.assertIn(
'A required package was not found',
1405 stderr.replace(
"\n",
""))
1407 raise Exception(
"Unknown import type")
1409 self.assertEqual(return_code, 0)
1410 self.assertIn(
"Build files", stdout)
1413 return_code, stdout, stderr =
run_program(
"cmake",
"--build .", cwd=install_prefix)
1415 if version ==
"3.00":
1416 self.assertEqual(return_code, 2)
1417 self.assertGreater(len(stderr), 0)
1419 self.assertEqual(return_code, 0)
1420 self.assertIn(
"Built target", stdout)
1423 return_code, stdout, stderr =
run_program(
"./test",
"", cwd=install_prefix)
1424 self.assertEqual(return_code, 0)
1427 return_code, stdout, stderr =
run_ns3(
"uninstall")
1428 self.assertIn(
"Built target uninstall", stdout)
1431 with open(version_file,
"w")
as f:
1435 NS3BuildBaseTestCase.cleaned_once =
False
1439 Tries to build scratch-simulator and subdir/scratch-simulator-subdir
1443 targets = {
"scratch/scratch-simulator":
"scratch-simulator",
1444 "scratch/scratch-simulator.cc":
"scratch-simulator",
1445 "scratch-simulator":
"scratch-simulator",
1446 "scratch/subdir/scratch-simulator-subdir":
"subdir_scratch-simulator-subdir",
1447 "subdir/scratch-simulator-subdir":
"subdir_scratch-simulator-subdir",
1448 "scratch-simulator-subdir":
"subdir_scratch-simulator-subdir",
1450 for (target_to_run, target_cmake)
in targets.items():
1452 build_line =
"target scratch_%s" % target_cmake
1453 return_code, stdout, stderr =
run_ns3(
"build %s" % target_to_run)
1454 self.assertEqual(return_code, 0)
1455 self.assertIn(build_line, stdout)
1458 return_code, stdout, stderr =
run_ns3(
"run %s --verbose" % target_to_run)
1459 self.assertEqual(return_code, 0)
1460 self.assertIn(build_line, stdout)
1461 stdout = stdout.replace(
"scratch_%s" % target_cmake,
"")
1462 self.assertIn(target_to_run.split(
"/")[-1].replace(
".cc",
""), stdout)
1464 NS3BuildBaseTestCase.cleaned_once =
False
1468 Test if cmake
is calling pybindgen through modulegen to generate
1469 the bindings source files correctly
1477 self.skipTest(
"Pybindgen is not available")
1481 self.assertEqual(len(python_scripts), 0)
1484 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-examples --enable-tests --enable-python-bindings")
1485 self.assertEqual(return_code, 0)
1488 core_bindings_generated_sources_path = os.path.join(ns3_path,
"build",
"src",
"core",
"bindings")
1489 core_bindings_sources_path = os.path.join(ns3_path,
"src",
"core",
"bindings")
1490 core_bindings_path = os.path.join(ns3_path,
"build",
"bindings",
"python",
"ns")
1491 core_bindings_header = os.path.join(core_bindings_generated_sources_path,
"ns3module.h")
1492 core_bindings_source = os.path.join(core_bindings_generated_sources_path,
"ns3module.cc")
1493 self.assertTrue(os.path.exists(core_bindings_header))
1494 self.assertTrue(os.path.exists(core_bindings_source))
1497 return_code, stdout, stderr =
run_ns3(
"build core-bindings")
1498 self.assertEqual(return_code, 0)
1501 self.assertGreater(len(
list(filter(
lambda x:
"_core" in x, os.listdir(core_bindings_path)))), 0)
1504 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" -- -DNS3_SCAN_PYTHON_BINDINGS=ON")
1505 self.assertEqual(return_code, 0)
1508 bindings_sources = os.listdir(core_bindings_sources_path)
1509 bindings_sources = [os.path.join(core_bindings_sources_path, y)
for y
in bindings_sources]
1511 [timestamps.update({x: os.stat(x)})
for x
in bindings_sources]
1514 return_code, stdout, stderr =
run_ns3(
"build core-apiscan")
1515 self.assertEqual(return_code, 0)
1518 generated_python_files = [
"callbacks_list.py",
"modulegen__gcc_LP64.py"]
1519 for binding_file
in timestamps.keys():
1520 if os.path.basename(binding_file)
in generated_python_files:
1521 self.assertTrue(os.path.exists(binding_file))
1522 self.assertGreater(os.stat(binding_file).st_size, 0)
1523 new_fstat = os.stat(binding_file)
1524 self.assertNotEqual(timestamps[binding_file].st_mtime, new_fstat.st_mtime)
1527 for f
in os.listdir(core_bindings_generated_sources_path):
1528 os.remove(os.path.join(core_bindings_generated_sources_path, f))
1531 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\"")
1532 self.assertEqual(return_code, 0)
1535 self.assertTrue(os.path.exists(core_bindings_header))
1536 self.assertTrue(os.path.exists(core_bindings_source))
1539 return_code, stdout, stderr =
run_ns3(
"build core-bindings")
1540 self.assertEqual(return_code, 0)
1543 self.assertGreater(len(
list(filter(
lambda x:
"_core" in x, os.listdir(core_bindings_path)))), 0)
1546 sys.path.insert(0, os.path.join(core_bindings_path,
".."))
1550 self.assertTrue(
True)
1553 return_code, stdout, stderr =
run_ns3(
"run sample-simulator.py")
1554 self.assertEqual(return_code, 0)
1557 return_code, stdout, stderr =
run_program(
"./test.py",
"-p src/core/examples/sample-simulator.py", python=
True)
1558 self.assertEqual(return_code, 0)
1562 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --disable-examples")
1563 self.assertEqual(return_code, 0)
1567 self.assertGreater(len(python_scripts), 0)
1570 return_code, stdout, stderr =
run_ns3(
"run sample-simulator.py")
1571 self.assertEqual(return_code, 0)
1573 NS3BuildBaseTestCase.cleaned_once =
False
1577 Test if ns3 can alert correctly
in case a shortcut collision happens
1582 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-examples")
1583 self.assertEqual(return_code, 0)
1586 shutil.copy(
"./examples/tutorial/second.cc",
"./scratch/second.cc")
1589 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-examples")
1590 self.assertEqual(return_code, 0)
1593 return_code, stdout, stderr =
run_ns3(
"build second")
1594 self.assertEqual(return_code, 1)
1596 'Build target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
1601 return_code, stdout, stderr =
run_ns3(
"build scratch/second")
1602 self.assertEqual(return_code, 0)
1606 return_code, stdout, stderr =
run_ns3(
"build tutorial/second")
1607 self.assertEqual(return_code, 0)
1611 return_code, stdout, stderr =
run_ns3(
"run second")
1612 self.assertEqual(return_code, 1)
1614 'Run target "second" is ambiguous. Try one of these: "scratch/second", "examples/tutorial/second"',
1619 return_code, stdout, stderr =
run_ns3(
"run scratch/second")
1620 self.assertEqual(return_code, 0)
1623 return_code, stdout, stderr =
run_ns3(
"run tutorial/second")
1624 self.assertEqual(return_code, 0)
1627 os.remove(
"./scratch/second.cc")
1632 Tests ns3 usage in more realistic scenarios
1636 cleaned_once = False
1640 Reuse cleaning/release configuration from NS3BaseTestCase
if flag
is cleaned
1641 Here examples, tests
and documentation are also enabled.
1644 if not NS3ExpectedUseTestCase.cleaned_once:
1645 NS3ExpectedUseTestCase.cleaned_once =
True
1646 NS3BaseTestCase.cleaned_once =
False
1650 return_code, stdout, stderr =
run_ns3(
"configure -G \"Unix Makefiles\" --enable-examples --enable-tests")
1654 self.assertTrue(os.path.exists(ns3_lock_filename))
1660 self.assertTrue(os.path.exists(ns3_lock_filename))
1667 Try to build the project
1670 return_code, stdout, stderr = run_ns3("build")
1671 self.assertEqual(return_code, 0)
1672 self.assertIn(
"Built target", stdout)
1674 self.assertTrue(os.path.exists(program))
1677 self.assertIn(module.replace(
"ns3-",
""),
";".join(libraries))
1678 self.assertIn(cmake_build_project_command, stdout)
1682 Try to build and run test-runner
1685 return_code, stdout, stderr = run_ns3('run "test-runner --list" --verbose')
1686 self.assertEqual(return_code, 0)
1687 self.assertIn(
"Built target test-runner", stdout)
1692 Try to build and run a library
1695 return_code, stdout, stderr = run_ns3("run core")
1696 self.assertEqual(return_code, 1)
1697 self.assertIn(
"Couldn't find the specified program: core", stderr)
1701 Try to build and run an unknown target
1704 return_code, stdout, stderr = run_ns3("run nonsense")
1705 self.assertEqual(return_code, 1)
1706 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
1710 Try to run test-runner without building
1713 return_code, stdout, stderr = run_ns3('run "test-runner --list" --no-build --verbose')
1714 self.assertEqual(return_code, 0)
1715 self.assertNotIn(
"Built target test-runner", stdout)
1720 Test ns3 fails to run a library
1723 return_code, stdout, stderr = run_ns3("run core --no-build")
1724 self.assertEqual(return_code, 1)
1725 self.assertIn(
"Couldn't find the specified program: core", stderr)
1729 Test ns3 fails to run an unknown program
1732 return_code, stdout, stderr = run_ns3("run nonsense --no-build")
1733 self.assertEqual(return_code, 1)
1734 self.assertIn(
"Couldn't find the specified program: nonsense", stderr)
1738 Test if scratch simulator
is executed through gdb
and lldb
1741 if shutil.which(
"gdb")
is None:
1742 self.skipTest(
"Missing gdb")
1744 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --gdb --verbose --no-build")
1745 self.assertEqual(return_code, 0)
1746 self.assertIn(
"scratch-simulator", stdout)
1747 self.assertIn(
"No debugging symbols found", stdout)
1751 Test if scratch simulator
is executed through valgrind
1754 if shutil.which(
"valgrind")
is None:
1755 self.skipTest(
"Missing valgrind")
1757 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --valgrind --verbose --no-build")
1758 self.assertEqual(return_code, 0)
1759 self.assertIn(
"scratch-simulator", stderr)
1760 self.assertIn(
"Memcheck", stderr)
1764 Test the doxygen target that does trigger a full build
1767 if shutil.which(
"doxygen")
is None:
1768 self.skipTest(
"Missing doxygen")
1770 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
1772 doxygen_files = [
"introspected-command-line.h",
"introspected-doxygen.h"]
1773 for filename
in doxygen_files:
1774 file_path = os.sep.join([doc_folder, filename])
1775 if os.path.exists(file_path):
1776 os.remove(file_path)
1783 return_code, stdout, stderr =
run_ns3(
"docs doxygen")
1784 self.assertEqual(return_code, 0)
1786 self.assertIn(
"Built target doxygen", stdout)
1790 Test the doxygen target that doesn't trigger a full build
1793 if shutil.which(
"doxygen")
is None:
1794 self.skipTest(
"Missing doxygen")
1802 return_code, stdout, stderr =
run_ns3(
"docs doxygen-no-build")
1803 self.assertEqual(return_code, 0)
1805 self.assertIn(
"Built target doxygen-no-build", stdout)
1809 Test every individual target for Sphinx-based documentation
1812 if shutil.which(
"sphinx-build")
is None:
1813 self.skipTest(
"Missing sphinx")
1815 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
1818 for target
in [
"contributing",
"manual",
"models",
"tutorial"]:
1820 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
1821 doc_temp_folder = os.sep.join([doc_folder, target,
"source-temp"])
1822 if os.path.exists(doc_build_folder):
1823 shutil.rmtree(doc_build_folder)
1824 if os.path.exists(doc_temp_folder):
1825 shutil.rmtree(doc_temp_folder)
1828 return_code, stdout, stderr =
run_ns3(
"docs %s" % target)
1829 self.assertEqual(return_code, 0)
1831 self.assertIn(
"Built target sphinx_%s" % target, stdout)
1834 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
1835 self.assertTrue(os.path.exists(doc_build_folder))
1838 for build_type
in [
"latex",
"html",
"singlehtml"]:
1839 self.assertTrue(os.path.exists(os.sep.join([doc_build_folder, build_type])))
1843 Test the documentation target that builds
1844 both doxygen and sphinx based documentation
1847 if shutil.which(
"doxygen")
is None:
1848 self.skipTest(
"Missing doxygen")
1849 if shutil.which(
"sphinx-build")
is None:
1850 self.skipTest(
"Missing sphinx")
1852 doc_folder = os.path.abspath(os.sep.join([
".",
"doc"]))
1861 for target
in [
"manual",
"models",
"tutorial"]:
1862 doc_build_folder = os.sep.join([doc_folder, target,
"build"])
1863 if os.path.exists(doc_build_folder):
1864 shutil.rmtree(doc_build_folder)
1866 return_code, stdout, stderr =
run_ns3(
"docs all")
1867 self.assertEqual(return_code, 0)
1869 self.assertIn(
"Built target sphinx", stdout)
1871 self.assertIn(
"Built target doxygen", stdout)
1875 Try to set ownership of scratch-simulator from current user to root,
1876 and change execution permissions
1881 sudo_password = os.getenv(
"SUDO_PASSWORD",
None)
1884 if sudo_password
is None:
1885 self.skipTest(
"SUDO_PASSWORD environment variable was not specified")
1888 self.assertFalse(enable_sudo
is True)
1891 return_code, stdout, stderr =
run_ns3(
'run scratch-simulator')
1892 self.assertEqual(return_code, 0)
1893 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
1895 scratch_simulator_path =
list(filter(
lambda x: x
if "scratch-simulator" in x
else None,
1899 prev_fstat = os.stat(scratch_simulator_path)
1902 return_code, stdout, stderr =
run_ns3(
'run scratch-simulator --enable-sudo',
1903 env={
"SUDO_PASSWORD": sudo_password})
1904 self.assertEqual(return_code, 0)
1905 self.assertIn(
"Built target scratch_scratch-simulator", stdout)
1907 fstat = os.stat(scratch_simulator_path)
1912 likely_fuse_mount = ((prev_fstat.st_mode & stat.S_ISUID) == (fstat.st_mode & stat.S_ISUID))
and \
1913 prev_fstat.st_uid == 0
1915 if sys.platform ==
"win32" or likely_fuse_mount:
1916 self.skipTest(
"Windows or likely a FUSE mount")
1919 self.assertEqual(fstat.st_uid, 0)
1920 self.assertEqual(fstat.st_mode & stat.S_ISUID, stat.S_ISUID)
1923 return_code, stdout, stderr =
run_ns3(
'configure --enable-sudo')
1924 self.assertEqual(return_code, 0)
1928 self.assertTrue(enable_sudo)
1932 if os.path.exists(executable):
1933 os.remove(executable)
1936 return_code, stdout, stderr =
run_ns3(
'build', env={
"SUDO_PASSWORD": sudo_password})
1937 self.assertEqual(return_code, 0)
1940 self.assertIn(
"chown root", stdout)
1941 self.assertIn(
"chmod u+s", stdout)
1943 self.assertIn(os.path.basename(executable), stdout)
1946 fstat = os.stat(scratch_simulator_path)
1947 self.assertEqual(fstat.st_uid, 0)
1948 self.assertEqual(fstat.st_mode & stat.S_ISUID, stat.S_ISUID)
1952 Check if command template
is working
1957 return_code0, stdout0, stderr0 =
run_ns3(
'run sample-simulator --command-template')
1958 self.assertEqual(return_code0, 2)
1959 self.assertIn(
"argument --command-template: expected one argument", stderr0)
1961 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template=" "')
1962 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --command-template " "')
1963 return_code3, stdout3, stderr3 =
run_ns3(
'run sample-simulator --command-template "echo "')
1964 self.assertEqual((return_code1, return_code2, return_code3), (1, 1, 1))
1965 self.assertIn(
"not all arguments converted during string formatting", stderr1)
1966 self.assertEqual(stderr1, stderr2)
1967 self.assertEqual(stderr2, stderr3)
1970 return_code4, stdout4, _ =
run_ns3(
'run sample-simulator --command-template "%s --PrintVersion" --verbose')
1971 return_code5, stdout5, _ =
run_ns3(
'run sample-simulator --command-template="%s --PrintVersion" --verbose')
1972 self.assertEqual((return_code4, return_code5), (0, 0))
1973 self.assertIn(
"sample-simulator --PrintVersion", stdout4)
1974 self.assertIn(
"sample-simulator --PrintVersion", stdout5)
1978 Check if all flavors of different argument passing to
1979 executable targets are working
1984 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --verbose')
1985 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template="%s --help" --verbose')
1986 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --verbose -- --help')
1988 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
1989 self.assertIn(
"sample-simulator --help", stdout0)
1990 self.assertIn(
"sample-simulator --help", stdout1)
1991 self.assertIn(
"sample-simulator --help", stdout2)
1994 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --help" --no-build')
1995 return_code1, stdout1, stderr1 =
run_ns3(
'run sample-simulator --command-template="%s --help" --no-build')
1996 return_code2, stdout2, stderr2 =
run_ns3(
'run sample-simulator --no-build -- --help')
1997 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
1998 self.assertEqual(stdout0, stdout1)
1999 self.assertEqual(stdout1, stdout2)
2000 self.assertEqual(stderr0, stderr1)
2001 self.assertEqual(stderr1, stderr2)
2004 return_code0, stdout0, stderr0 =
run_ns3(
'run "sample-simulator --PrintGlobals" --verbose')
2005 return_code1, stdout1, stderr1 =
run_ns3(
'run "sample-simulator --PrintGroups" --verbose')
2006 return_code2, stdout2, stderr2 =
run_ns3(
'run "sample-simulator --PrintTypeIds" --verbose')
2008 self.assertEqual((return_code0, return_code1, return_code2), (0, 0, 0))
2009 self.assertIn(
"sample-simulator --PrintGlobals", stdout0)
2010 self.assertIn(
"sample-simulator --PrintGroups", stdout1)
2011 self.assertIn(
"sample-simulator --PrintTypeIds", stdout2)
2014 cmd =
'run "sample-simulator --PrintGlobals" --command-template="%s --PrintGroups" --verbose -- --PrintTypeIds'
2015 return_code, stdout, stderr =
run_ns3(cmd)
2016 self.assertEqual(return_code, 0)
2021 self.assertIn(
"sample-simulator --PrintGroups --PrintGlobals --PrintTypeIds", stdout)
2024 cmd0 =
'run sample-simulator --command-template="%s " --PrintTypeIds'
2025 cmd1 =
'run sample-simulator --PrintTypeIds'
2027 return_code0, stdout0, stderr0 =
run_ns3(cmd0)
2028 return_code1, stdout1, stderr1 =
run_ns3(cmd1)
2029 self.assertEqual((return_code0, return_code1), (1, 1))
2030 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr0)
2031 self.assertIn(
"To forward configuration or runtime options, put them after '--'", stderr1)
2035 Test if scratch simulator
is executed through lldb
2038 if shutil.which(
"lldb")
is None:
2039 self.skipTest(
"Missing lldb")
2041 return_code, stdout, stderr =
run_ns3(
"run scratch-simulator --lldb --verbose --no-build")
2042 self.assertEqual(return_code, 0)
2043 self.assertIn(
"scratch-simulator", stdout)
2044 self.assertIn(
"(lldb) target create", stdout)
2047if __name__ ==
'__main__':
2048 loader = unittest.TestLoader()
2049 suite = unittest.TestSuite()
2052 suite.addTests(loader.loadTestsFromTestCase(NS3UnusedSourcesTestCase))
2053 suite.addTests(loader.loadTestsFromTestCase(NS3CommonSettingsTestCase))
2054 suite.addTests(loader.loadTestsFromTestCase(NS3ConfigureBuildProfileTestCase))
2055 suite.addTests(loader.loadTestsFromTestCase(NS3ConfigureTestCase))
2056 suite.addTests(loader.loadTestsFromTestCase(NS3BuildBaseTestCase))
2057 suite.addTests(loader.loadTestsFromTestCase(NS3ExpectedUseTestCase))
2060 tests = dict(map(
lambda x: (x._testMethodName, x), suite._tests))
2070 ns3rc_script_bak = ns3rc_script +
".bak"
2071 if os.path.exists(ns3rc_script)
and not os.path.exists(ns3rc_script_bak):
2072 shutil.move(ns3rc_script, ns3rc_script_bak)
2075 runner = unittest.TextTestRunner(failfast=
True)
2076 result = runner.run(suite)
2079 if os.path.exists(ns3rc_script_bak):
2080 shutil.move(ns3rc_script_bak, ns3rc_script)
Generic test case with basic function inherited by more complex tests.
def config_ok(self, return_code, stdout)
Check if configuration for release mode worked normally.
ns3_executables
ns3_executables holds a list of executables in .lock-ns3
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
Tests ns3 regarding building the project.
def test_06_TestVersionFile(self)
Test if changing the version file affects the library names.
def test_01_BuildExistingTargets(self)
Try building the core library.
def test_10_PybindgenBindings(self)
Test if cmake is calling pybindgen through modulegen to generate the bindings source files correctly.
def test_08_InstallationAndUninstallation(self)
Tries setting a ns3 version, then installing it.
def test_11_AmbiguityCheck(self)
Test if ns3 can alert correctly in case a shortcut collision happens.
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_03_BuildProject(self)
Try building the project:
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
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
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.
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
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.
ns3_executables
ns3_executables holds a list of executables in .lock-ns3
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 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
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 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()
def run_ns3(args, env=None)
Runs the ns3 wrapper script with arguments.