about summary refs log tree commit diff
path: root/lib/tests/modules
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2024-04-09 20:48:44 +0200
committerGitHub <noreply@github.com>2024-04-09 20:48:44 +0200
commit4f1d724b82db61237b5d7c669841b5f596e08e7f (patch)
treee0a02af4d45c5155d83201cfd9b2049f2594cd6b /lib/tests/modules
parent40d8229671633b1db7db5d28ae96969e3f52beb0 (diff)
parent35fe538330b738b90d527d908ee487e38d42de40 (diff)
Merge pull request #284551 from hercules-ci/types-attrTag
Add `types.attrTag`
Diffstat (limited to 'lib/tests/modules')
-rw-r--r--lib/tests/modules/docs.nix41
-rw-r--r--lib/tests/modules/types-attrTag-wrong-decl.nix14
-rw-r--r--lib/tests/modules/types-attrTag.nix135
3 files changed, 190 insertions, 0 deletions
diff --git a/lib/tests/modules/docs.nix b/lib/tests/modules/docs.nix
new file mode 100644
index 0000000000000..225aa7eac1de8
--- /dev/null
+++ b/lib/tests/modules/docs.nix
@@ -0,0 +1,41 @@
+/*
+  A basic documentation generating module.
+  Declares and defines a `docs` option, suitable for making assertions about
+  the extraction "phase" of documentation generation.
+ */
+{ lib, options, ... }:
+
+let
+  inherit (lib)
+    head
+    length
+    mkOption
+    types
+  ;
+
+  traceListSeq = l: v: lib.foldl' (a: b: lib.traceSeq b a) v l;
+
+in
+
+{
+  options.docs = mkOption {
+    type = types.lazyAttrsOf types.raw;
+    description = ''
+      All options to be rendered, without any visibility filtering applied.
+    '';
+  };
+  config.docs =
+    lib.zipAttrsWith
+      (name: values:
+        if length values > 1 then
+          traceListSeq values
+          abort "Multiple options with the same name: ${name}"
+        else
+          assert length values == 1;
+          head values
+      )
+      (map
+        (opt: { ${opt.name} = opt; })
+        (lib.optionAttrSetToDocList options)
+      );
+}
diff --git a/lib/tests/modules/types-attrTag-wrong-decl.nix b/lib/tests/modules/types-attrTag-wrong-decl.nix
new file mode 100644
index 0000000000000..d03370bc10da4
--- /dev/null
+++ b/lib/tests/modules/types-attrTag-wrong-decl.nix
@@ -0,0 +1,14 @@
+{ lib, ... }:
+let
+  inherit (lib) types mkOption;
+in
+{
+  options = {
+    opt = mkOption {
+      type = types.attrTag {
+        int = types.int;
+      };
+      default = { int = 1; };
+    };
+  };
+}
diff --git a/lib/tests/modules/types-attrTag.nix b/lib/tests/modules/types-attrTag.nix
new file mode 100644
index 0000000000000..b2e5158bb44b6
--- /dev/null
+++ b/lib/tests/modules/types-attrTag.nix
@@ -0,0 +1,135 @@
+{ lib, config, options, ... }:
+let
+  inherit (lib) mkOption types;
+  forceDeep = x: builtins.deepSeq x x;
+  mergedSubOption = (options.merged.type.getSubOptions options.merged.loc).extensible."merged.<name>";
+in
+{
+  options = {
+    intStrings = mkOption {
+      type = types.attrsOf
+        (types.attrTag {
+          left = mkOption {
+            type = types.int;
+          };
+          right = mkOption {
+            type = types.str;
+          };
+        });
+    };
+    nested = mkOption {
+      type = types.attrTag {
+        left = mkOption {
+          type = types.int;
+        };
+        right = mkOption {
+          type = types.attrTag {
+            left = mkOption {
+              type = types.int;
+            };
+            right = mkOption {
+              type = types.str;
+            };
+          };
+        };
+      };
+    };
+    merged = mkOption {
+      type = types.attrsOf (
+        types.attrTag {
+          yay = mkOption {
+            type = types.int;
+          };
+          extensible = mkOption {
+            type = types.enum [ "foo" ];
+          };
+        }
+      );
+    };
+    submodules = mkOption {
+      type = types.attrsOf (
+        types.attrTag {
+          foo = mkOption {
+            type = types.submodule {
+              options = {
+                bar = mkOption {
+                  type = types.int;
+                };
+              };
+            };
+          };
+          qux = mkOption {
+            type = types.str;
+            description = "A qux for when you don't want a foo";
+          };
+        }
+      );
+    };
+    okChecks = mkOption {};
+  };
+  imports = [
+    ./docs.nix
+    {
+      options.merged = mkOption {
+        type = types.attrsOf (
+          types.attrTag {
+            nay = mkOption {
+              type = types.bool;
+            };
+            extensible = mkOption {
+              type = types.enum [ "bar" ];
+            };
+          }
+        );
+      };
+    }
+  ];
+  config = {
+    intStrings.syntaxError = 1;
+    intStrings.syntaxError2 = {};
+    intStrings.syntaxError3 = { a = true; b = true; };
+    intStrings.syntaxError4 = lib.mkMerge [ { a = true; } { b = true; } ];
+    intStrings.mergeError = lib.mkMerge [ { int = throw "do not eval"; } { string = throw "do not eval"; } ];
+    intStrings.badTagError.rite = throw "do not eval";
+    intStrings.badTagTypeError.left = "bad";
+    intStrings.numberOne.left = 1;
+    intStrings.hello.right = "hello world";
+    nested.right.left = "not a number";
+    merged.negative.nay = false;
+    merged.positive.yay = 100;
+    merged.extensi-foo.extensible = "foo";
+    merged.extensi-bar.extensible = "bar";
+    okChecks = builtins.addErrorContext "while evaluating the assertions" (
+      assert config.intStrings.hello == { right = "hello world"; };
+      assert config.intStrings.numberOne == { left = 1; };
+      assert config.merged.negative == { nay = false; };
+      assert config.merged.positive == { yay = 100; };
+      assert config.merged.extensi-foo == { extensible = "foo"; };
+      assert config.merged.extensi-bar == { extensible = "bar"; };
+      assert config.docs."submodules.<name>.foo.bar".type == "signed integer";
+      assert config.docs."submodules.<name>.qux".type == "string";
+      assert config.docs."submodules.<name>.qux".declarations == [ __curPos.file ];
+      assert config.docs."submodules.<name>.qux".loc == [ "submodules" "<name>" "qux" ];
+      assert config.docs."submodules.<name>.qux".name == "submodules.<name>.qux";
+      assert config.docs."submodules.<name>.qux".description == "A qux for when you don't want a foo";
+      assert config.docs."submodules.<name>.qux".readOnly == false;
+      assert config.docs."submodules.<name>.qux".visible == true;
+      # Not available (yet?)
+      # assert config.docs."submodules.<name>.qux".declarationsWithPositions == [ ... ];
+      assert options.submodules.declarations == [ __curPos.file ];
+      assert lib.length options.submodules.declarationPositions == 1;
+      assert (lib.head options.submodules.declarationPositions).file == __curPos.file;
+      assert options.merged.declarations == [ __curPos.file __curPos.file ];
+      assert lib.length options.merged.declarationPositions == 2;
+      assert (lib.elemAt options.merged.declarationPositions 0).file == __curPos.file;
+      assert (lib.elemAt options.merged.declarationPositions 1).file == __curPos.file;
+      assert (lib.elemAt options.merged.declarationPositions 0).line != (lib.elemAt options.merged.declarationPositions 1).line;
+      assert mergedSubOption.declarations == [ __curPos.file __curPos.file ];
+      assert lib.length mergedSubOption.declarationPositions == 2;
+      assert (lib.elemAt mergedSubOption.declarationPositions 0).file == __curPos.file;
+      assert (lib.elemAt mergedSubOption.declarationPositions 1).file == __curPos.file;
+      assert (lib.elemAt mergedSubOption.declarationPositions 0).line != (lib.elemAt mergedSubOption.declarationPositions 1).line;
+      assert lib.length config.docs."merged.<name>.extensible".declarations == 2;
+      true);
+  };
+}