···25252626## Testing changes to the test framework {#sec-test-the-test-framework}
27272828+We currently have limited unit tests for the framework itself. You may run these with `nix-build -A nixosTests.nixos-test-driver`.
2929+2830When making significant changes to the test framework, we run the tests on Hydra, to avoid disrupting the larger NixOS project.
29313032For this, we use the `python-test-refactoring` branch in the `NixOS/nixpkgs` repository, and its [corresponding Hydra jobset](https://hydra.nixos.org/jobset/nixos/python-test-refactoring).
···130130start_all()
131131```
132132133133+If the hostname of a node contains characters that can't be used in a
134134+Python variable name, those characters will be replaced with
135135+underscores in the variable name, so `nodes.machine-a` will be exposed
136136+to Python as `machine_a`.
137137+133138## Machine objects {#ssec-machine-objects}
134139135140The following methods are available on machine objects:
+6-1
nixos/lib/test-driver/test_driver/driver.py
···22from pathlib import Path
33from typing import Any, Dict, Iterator, List, Union, Optional, Callable, ContextManager
44import os
55+import re
56import tempfile
6778from test_driver.logger import rootlog
···2627 f"The directory defined by TMPDIR, TEMP, TMP, or CWD: {tmp_dir} is not writeable"
2728 )
2829 return tmp_dir
3030+3131+3232+def pythonize_name(name: str) -> str:
3333+ return re.sub(r"^[^A-z_]|[^A-z0-9_]", "_", name)
293430353136class Driver:
···113118 polling_condition=self.polling_condition,
114119 Machine=Machine, # for typing
115120 )
116116- machine_symbols = {m.name: m for m in self.machines}
121121+ machine_symbols = {pythonize_name(m.name): m for m in self.machines}
117122 # If there's exactly one machine, make it available under the name
118123 # "machine", even if it's not called that.
119124 if len(self.machines) == 1:
+11-20
nixos/lib/testing/driver.nix
···2121 in
2222 nodesList ++ lib.optional (lib.length nodesList == 1 && !lib.elem "machine" nodesList) "machine";
23232424- # TODO: This is an implementation error and needs fixing
2525- # the testing famework cannot legitimately restrict hostnames further
2626- # beyond RFC1035
2727- invalidNodeNames = lib.filter
2828- (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
2929- nodeHostNames;
2424+ pythonizeName = name:
2525+ let
2626+ head = lib.substring 0 1 name;
2727+ tail = lib.substring 1 (-1) name;
2828+ in
2929+ (if builtins.match "[A-z_]" head == null then "_" else head) +
3030+ lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
30313132 uniqueVlans = lib.unique (builtins.concatLists vlans);
3233 vlanNames = map (i: "vlan${toString i}: VLan;") uniqueVlans;
3333- machineNames = map (name: "${name}: Machine;") nodeHostNames;
3434+ pythonizedNames = map pythonizeName nodeHostNames;
3535+ machineNames = map (name: "${name}: Machine;") pythonizedNames;
34363535- withChecks =
3636- if lib.length invalidNodeNames > 0 then
3737- throw ''
3838- Cannot create machines out of (${lib.concatStringsSep ", " invalidNodeNames})!
3939- All machines are referenced as python variables in the testing framework which will break the
4040- script when special characters are used.
4141-4242- This is an IMPLEMENTATION ERROR and needs to be fixed. Meanwhile,
4343- please stick to alphanumeric chars and underscores as separation.
4444- ''
4545- else
4646- lib.warnIf config.skipLint "Linting is disabled";
3737+ withChecks = lib.warnIf config.skipLint "Linting is disabled";
47384839 driver =
4940 hostPkgs.runCommand "nixos-test-driver-${config.name}"
···8778 ${testDriver}/bin/generate-driver-symbols
8879 ${lib.optionalString (!config.skipLint) ''
8980 PYFLAKES_BUILTINS="$(
9090- echo -n ${lib.escapeShellArg (lib.concatStringsSep "," nodeHostNames)},
8181+ echo -n ${lib.escapeShellArg (lib.concatStringsSep "," pythonizedNames)},
9182 < ${lib.escapeShellArg "driver-symbols"}
9283 )" ${hostPkgs.python3Packages.pyflakes}/bin/pyflakes $out/test-script
9384 ''}
···11+{
22+ name = "nixos-test-driver.node-name";
33+ nodes = {
44+ "ok" = { };
55+66+ # Valid node name, but not a great host name.
77+ "one_two" = { };
88+99+ # Valid node name, good host name
1010+ "a-b" = { };
1111+1212+ # TODO: would be nice to test these eval failures
1313+ # Not allowed by lib/testing/network.nix (yet?)
1414+ # "foo.bar" = { };
1515+ # Not allowed.
1616+ # "not ok" = { }; # not ok
1717+ };
1818+1919+ testScript = ''
2020+ start_all()
2121+2222+ with subtest("python vars exist and machines are reachable through test backdoor"):
2323+ ok.succeed("true")
2424+ one_two.succeed("true")
2525+ a_b.succeed("true")
2626+2727+ with subtest("hostname is derived from the node name"):
2828+ ok.succeed("hostname | tee /dev/stderr | grep '^ok$'")
2929+ one_two.succeed("hostname | tee /dev/stderr | grep '^onetwo$'")
3030+ a_b.succeed("hostname | tee /dev/stderr | grep '^a-b$'")
3131+3232+ '';
3333+}
···2828 "--with-long-double-128"
2929 "--with-long-double-format=${gcc.long-double-format or "ieee"}"
3030 ]))
3131+ (lib.optional targetPlatform.isMips64n32 "--disable-libsanitizer") # libsanitizer does not compile on mips64n32
3132]
···8899stdenv.mkDerivation rec {
1010 pname = "openfortivpn";
1111- version = "1.20.1";
1111+ version = "1.20.2";
12121313 src = fetchFromGitHub {
1414 owner = "adrienverge";
1515 repo = pname;
1616 rev = "v${version}";
1717- sha256 = "sha256-xsH/Nb1/69R2EvAisDnrHWehjDIMBmElCV6evuTwBIQ=";
1717+ sha256 = "sha256-Ml1aVvF+kqlSTuzZeHG8Ry+BA24YdWACwQNlO2K+FGo=";
1818 };
19192020 # we cannot write the config file to /etc and as we don't need the file, so drop it