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.