4 from pathlib
import Path
8 from test_driver
.driver
import Driver
9 from test_driver
.logger
import (
17 class EnvDefault(argparse
.Action
):
18 """An argpars Action that takes values from the specified
19 environment variable as the flags default value.
22 def __init__(self
, envvar
, required
=False, default
=None, nargs
=None, **kwargs
): # type: ignore
23 if not default
and envvar
:
24 if envvar
in os
.environ
:
25 if nargs
is not None and (nargs
.isdigit() or nargs
in ["*", "+"]):
26 default
= os
.environ
[envvar
].split()
28 default
= os
.environ
[envvar
]
30 kwargs
["help"] + f
" (default from environment: {default})"
32 if required
and default
:
34 super().__init
__(default
=default
, required
=required
, nargs
=nargs
, **kwargs
)
36 def __call__(self
, parser
, namespace
, values
, option_string
=None): # type: ignore
37 setattr(namespace
, self
.dest
, values
)
40 def writeable_dir(arg
: str) -> Path
:
41 """Raises an ArgumentTypeError if the given argument isn't a writeable directory
42 Note: We want to fail as early as possible if a directory isn't writeable,
43 since an executed nixos-test could fail (very late) because of the test-driver
44 writing in a directory without proper permissions.
48 raise argparse
.ArgumentTypeError(f
"{path} is not a directory")
49 if not os
.access(path
, os
.W_OK
):
50 raise argparse
.ArgumentTypeError(f
"{path} is not a writeable directory")
55 arg_parser
= argparse
.ArgumentParser(prog
="nixos-test-driver")
56 arg_parser
.add_argument(
59 help="re-use a VM state coming from a previous run",
62 arg_parser
.add_argument(
65 help="drop into a python repl and run the tests interactively",
66 action
=argparse
.BooleanOptionalAction
,
68 arg_parser
.add_argument(
70 metavar
="START-SCRIPT",
72 envvar
="startScripts",
74 help="start scripts for participating virtual machines",
76 arg_parser
.add_argument(
82 help="vlans to span by the driver",
84 arg_parser
.add_argument(
87 metavar
="GLOBAL_TIMEOUT",
89 envvar
="globalTimeout",
90 help="Timeout in seconds for the whole test",
92 arg_parser
.add_argument(
95 help="""The path to the directory where outputs copied from the VM will be placed.
96 By e.g. Machine.copy_from_vm or Machine.screenshot""",
100 arg_parser
.add_argument(
102 help="Enable JunitXML report generation to the given path",
105 arg_parser
.add_argument(
109 help="the test script to run",
113 args
= arg_parser
.parse_args()
115 output_directory
= args
.output_directory
.resolve()
116 logger
= CompositeLogger([TerminalLogger()])
118 if "LOGFILE" in os
.environ
.keys():
119 logger
.add_logger(XMLLogger(os
.environ
["LOGFILE"]))
122 logger
.add_logger(JunitXMLLogger(output_directory
/ args
.junit_xml
))
124 if not args
.keep_vm_state
:
125 logger
.info("Machine state will be reset. To keep it, pass --keep-vm-state")
130 args
.testscript
.read_text(),
137 history_dir
= os
.getcwd()
138 history_path
= os
.path
.join(history_dir
, ".nixos-test-history")
140 driver
.test_symbols(),
142 history_filename
=history_path
,
148 logger
.info(f
"test script finished in {(toc-tic):.2f}s")
151 def generate_driver_symbols() -> None:
153 This generates a file with symbols of the test-driver code that can be used
154 in user's test scripts. That list is then used by pyflakes to lint those
157 d
= Driver([], [], "", Path(), CompositeLogger([]))
158 test_symbols
= d
.test_symbols()
159 with
open("driver-symbols", "w") as fp
:
160 fp
.write(",".join(test_symbols
.keys()))