···56```ShellSession
7$ nix-build nixos/tests/login.nix -A driverInteractive
8-$ ./result/bin/nixos-test-driver
9starting VDE switch for network 1
10>
11```
···24you to inspect the state of the VMs after the test (e.g. to debug the
25test script).
2627-To just start and experiment with the VMs, run:
28-29-```ShellSession
30-$ nix-build nixos/tests/login.nix -A driverInteractive
31-$ ./result/bin/nixos-run-vms
32-```
33-34-The script `nixos-run-vms` starts the virtual machines defined by test.
35-36You can re-use the VM states coming from a previous run by setting the
37`--keep-vm-state` flag.
3839```ShellSession
40-$ ./result/bin/nixos-run-vms --keep-vm-state
41```
4243The machine state is stored in the `$TMPDIR/vm-state-machinename`
···56```ShellSession
7$ nix-build nixos/tests/login.nix -A driverInteractive
8+$ ./result/bin/nixos-test-driver --interactive
9starting VDE switch for network 1
10>
11```
···24you to inspect the state of the VMs after the test (e.g. to debug the
25test script).
2600000000027You can re-use the VM states coming from a previous run by setting the
28`--keep-vm-state` flag.
2930```ShellSession
31+$ ./result/bin/nixos-test-driver --interactive --keep-vm-state
32```
3334The machine state is stored in the `$TMPDIR/vm-state-machinename`
···6 </para>
7 <programlisting>
8$ nix-build nixos/tests/login.nix -A driverInteractive
9-$ ./result/bin/nixos-test-driver
10starting VDE switch for network 1
11>
12</programlisting>
···26 the test (e.g. to debug the test script).
27 </para>
28 <para>
29- To just start and experiment with the VMs, run:
30- </para>
31- <programlisting>
32-$ nix-build nixos/tests/login.nix -A driverInteractive
33-$ ./result/bin/nixos-run-vms
34-</programlisting>
35- <para>
36- The script <literal>nixos-run-vms</literal> starts the virtual
37- machines defined by test.
38- </para>
39- <para>
40 You can re-use the VM states coming from a previous run by setting
41 the <literal>--keep-vm-state</literal> flag.
42 </para>
43 <programlisting>
44-$ ./result/bin/nixos-run-vms --keep-vm-state
45</programlisting>
46 <para>
47 The machine state is stored in the
···6 </para>
7 <programlisting>
8$ nix-build nixos/tests/login.nix -A driverInteractive
9+$ ./result/bin/nixos-test-driver --interactive
10starting VDE switch for network 1
11>
12</programlisting>
···26 the test (e.g. to debug the test script).
27 </para>
28 <para>
0000000000029 You can re-use the VM states coming from a previous run by setting
30 the <literal>--keep-vm-state</literal> flag.
31 </para>
32 <programlisting>
33+$ ./result/bin/nixos-test-driver --interactive --keep-vm-state
34</programlisting>
35 <para>
36 The machine state is stored in the
+73-28
nixos/lib/test-driver/test-driver.py
···24import telnetlib
25import tempfile
26import time
27-import traceback
28import unicodedata
2930CHAR_TO_KEY = {
···930 machine.wait_for_shutdown()
931932933-def test_script() -> None:
934- exec(os.environ["testScript"])
935-936-937-def run_tests() -> None:
938 global machines
939- tests = os.environ.get("tests", None)
940- if tests is not None:
941- with log.nested("running the VM test script"):
942- try:
943- exec(tests, globals())
944- except Exception as e:
945- eprint("error: ")
946- traceback.print_exc()
947- sys.exit(1)
948 else:
949- ptpython.repl.embed(locals(), globals())
950-951- # TODO: Collect coverage data
952-953- for machine in machines:
954- if machine.is_up():
955- machine.execute("sync")
956957958def serial_stdout_on() -> None:
···965 log._print_serial_logs = False
9669670000000000000000000000000968@contextmanager
969def subtest(name: str) -> Iterator[None]:
970 with log.nested(name):
···986 help="re-use a VM state coming from a previous run",
987 action="store_true",
988 )
989- (cli_args, vm_scripts) = arg_parser.parse_known_args()
00000000000000000000000000000000000990991 log = Logger()
992993- vlan_nrs = list(dict.fromkeys(os.environ.get("VLANS", "").split()))
994- vde_sockets = [create_vlan(v) for v in vlan_nrs]
995 for nr, vde_socket, _, _ in vde_sockets:
996 os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
997998 machines = [
999- create_machine({"startCommand": s, "keepVmState": cli_args.keep_vm_state})
1000- for s in vm_scripts
1001 ]
1002 machine_eval = [
1003 "{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines)
···1017 log.close()
10181019 tic = time.time()
1020- run_tests()
1021 toc = time.time()
1022 print("test script finished in {:.2f}s".format(toc - tic))
···24import telnetlib
25import tempfile
26import time
027import unicodedata
2829CHAR_TO_KEY = {
···929 machine.wait_for_shutdown()
930931932+def run_tests(interactive: bool = False) -> None:
0000933 global machines
934+ if interactive:
935+ ptpython.repl.embed(globals(), locals())
0000000936 else:
937+ test_script()
938+ # TODO: Collect coverage data
939+ for machine in machines:
940+ if machine.is_up():
941+ machine.execute("sync")
00942943944def serial_stdout_on() -> None:
···951 log._print_serial_logs = False
952953954+class EnvDefault(argparse.Action):
955+ """An argpars Action that takes values from the specified
956+ environment variable as the flags default value.
957+ """
958+959+ def __init__(self, envvar, required=False, default=None, nargs=None, **kwargs): # type: ignore
960+ if not default and envvar:
961+ if envvar in os.environ:
962+ if nargs is not None and (nargs.isdigit() or nargs in ["*", "+"]):
963+ default = os.environ[envvar].split()
964+ else:
965+ default = os.environ[envvar]
966+ kwargs["help"] = (
967+ kwargs["help"] + f" (default from environment: {default})"
968+ )
969+ if required and default:
970+ required = False
971+ super(EnvDefault, self).__init__(
972+ default=default, required=required, nargs=nargs, **kwargs
973+ )
974+975+ def __call__(self, parser, namespace, values, option_string=None): # type: ignore
976+ setattr(namespace, self.dest, values)
977+978+979@contextmanager
980def subtest(name: str) -> Iterator[None]:
981 with log.nested(name):
···997 help="re-use a VM state coming from a previous run",
998 action="store_true",
999 )
1000+ arg_parser.add_argument(
1001+ "-I",
1002+ "--interactive",
1003+ help="drop into a python repl and run the tests interactively",
1004+ action="store_true",
1005+ )
1006+ arg_parser.add_argument(
1007+ "--start-scripts",
1008+ metavar="START-SCRIPT",
1009+ action=EnvDefault,
1010+ envvar="startScripts",
1011+ nargs="*",
1012+ help="start scripts for participating virtual machines",
1013+ )
1014+ arg_parser.add_argument(
1015+ "--vlans",
1016+ metavar="VLAN",
1017+ action=EnvDefault,
1018+ envvar="vlans",
1019+ nargs="*",
1020+ help="vlans to span by the driver",
1021+ )
1022+ arg_parser.add_argument(
1023+ "testscript",
1024+ action=EnvDefault,
1025+ envvar="testScript",
1026+ help="the test script to run",
1027+ type=pathlib.Path,
1028+ )
1029+1030+ args = arg_parser.parse_args()
1031+ global test_script
1032+1033+ def test_script() -> None:
1034+ with log.nested("running the VM test script"):
1035+ exec(pathlib.Path(args.testscript).read_text(), globals())
10361037 log = Logger()
10381039+ vde_sockets = [create_vlan(v) for v in args.vlans]
01040 for nr, vde_socket, _, _ in vde_sockets:
1041 os.environ["QEMU_VDE_SOCKET_{}".format(nr)] = vde_socket
10421043 machines = [
1044+ create_machine({"startCommand": s, "keepVmState": args.keep_vm_state})
1045+ for s in args.start_scripts
1046 ]
1047 machine_eval = [
1048 "{0} = machines[{1}]".format(m.name, idx) for idx, m in enumerate(machines)
···1062 log.close()
10631064 tic = time.time()
1065+ run_tests(args.interactive)
1066 toc = time.time()
1067 print("test script finished in {:.2f}s".format(toc - tic))