1testModuleArgs@{
2 config,
3 lib,
4 hostPkgs,
5 nodes,
6 moduleType,
7 ...
8}:
9let
10 inherit (lib) mkOption types;
11 inherit (types) either str functionTo;
12in
13{
14 options = {
15 testScript = mkOption {
16 type = either str (functionTo str);
17 description = ''
18 A series of python declarations and statements that you write to perform
19 the test.
20 '';
21 };
22 testScriptString = mkOption {
23 type = str;
24 readOnly = true;
25 internal = true;
26 };
27
28 includeTestScriptReferences = mkOption {
29 type = types.bool;
30 default = true;
31 internal = true;
32 };
33 withoutTestScriptReferences = mkOption {
34 type = moduleType;
35 description = ''
36 A parallel universe where the testScript is invalid and has no references.
37 '';
38 internal = true;
39 visible = false;
40 };
41 };
42 config = {
43 withoutTestScriptReferences.includeTestScriptReferences = false;
44 withoutTestScriptReferences.testScript = lib.mkForce "testscript omitted";
45
46 testScriptString =
47 if lib.isFunction config.testScript then
48 config.testScript {
49 nodes = lib.mapAttrs (
50 k: v:
51 if v.virtualisation.useNixStoreImage then
52 # prevent infinite recursion when testScript would
53 # reference v's toplevel
54 config.withoutTestScriptReferences.nodesCompat.${k}
55 else
56 # reuse memoized config
57 v
58 ) config.nodesCompat;
59 }
60 else
61 config.testScript;
62
63 defaults =
64 { config, name, ... }:
65 {
66 # Make sure all derivations referenced by the test
67 # script are available on the nodes. When the store is
68 # accessed through 9p, this isn't important, since
69 # everything in the store is available to the guest,
70 # but when building a root image it is, as all paths
71 # that should be available to the guest has to be
72 # copied to the image.
73 virtualisation.additionalPaths =
74 lib.optional
75 # A testScript may evaluate nodes, which has caused
76 # infinite recursions. The demand cycle involves:
77 # testScript -->
78 # nodes -->
79 # toplevel -->
80 # additionalPaths -->
81 # hasContext testScript' -->
82 # testScript (ad infinitum)
83 # If we don't need to build an image, we can break this
84 # cycle by short-circuiting when useNixStoreImage is false.
85 (
86 config.virtualisation.useNixStoreImage
87 && builtins.hasContext testModuleArgs.config.testScriptString
88 && testModuleArgs.config.includeTestScriptReferences
89 )
90 (hostPkgs.writeStringReferencesToFile testModuleArgs.config.testScriptString);
91 };
92 };
93}