diff options
author | Alyssa Ross <hi@alyssa.is> | 2024-05-03 15:14:25 +0200 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2024-05-07 11:19:19 +0200 |
commit | d92b2b6a1bbd322dd65a8b6f51019610d350046e (patch) | |
tree | 7f7c21927b9cc05676501f297c51eb76b49e326c /nixpkgs/lib/tests | |
parent | 93c9e56b40530cc627d921cfc255c05b495d4017 (diff) | |
parent | 49050352f602fe87d16ff7b2b6a05b79eb20dc6f (diff) | |
download | nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.tar nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.tar.gz nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.tar.bz2 nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.tar.lz nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.tar.xz nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.tar.zst nixlib-d92b2b6a1bbd322dd65a8b6f51019610d350046e.zip |
Merge remote-tracking branch 'nixpkgs/nixos-unstable-small'
Conflicts: nixpkgs/nixos/modules/services/mail/mailman.nix nixpkgs/nixos/modules/services/mail/public-inbox.nix nixpkgs/pkgs/build-support/go/module.nix
Diffstat (limited to 'nixpkgs/lib/tests')
-rw-r--r-- | nixpkgs/lib/tests/misc.nix | 157 | ||||
-rwxr-xr-x | nixpkgs/lib/tests/modules.sh | 12 | ||||
-rw-r--r-- | nixpkgs/lib/tests/modules/doRename-condition.nix | 4 | ||||
-rw-r--r-- | nixpkgs/lib/tests/modules/docs.nix | 41 | ||||
-rw-r--r-- | nixpkgs/lib/tests/modules/types-attrTag-wrong-decl.nix | 14 | ||||
-rw-r--r-- | nixpkgs/lib/tests/modules/types-attrTag.nix | 135 | ||||
-rw-r--r-- | nixpkgs/lib/tests/release.nix | 2 | ||||
-rw-r--r-- | nixpkgs/lib/tests/systems.nix | 6 |
8 files changed, 335 insertions, 36 deletions
diff --git a/nixpkgs/lib/tests/misc.nix b/nixpkgs/lib/tests/misc.nix index 6f1d9039db80..6774939023d2 100644 --- a/nixpkgs/lib/tests/misc.nix +++ b/nixpkgs/lib/tests/misc.nix @@ -1,17 +1,21 @@ -/* -Nix evaluation tests for various lib functions. +/** + Nix evaluation tests for various lib functions. -Since these tests are implemented with Nix evaluation, error checking is limited to what `builtins.tryEval` can detect, which is `throw`'s and `abort`'s, without error messages. -If you need to test error messages or more complex evaluations, see ./modules.sh, ./sources.sh or ./filesystem.sh as examples. + Since these tests are implemented with Nix evaluation, + error checking is limited to what `builtins.tryEval` can detect, + which is `throw`'s and `abort`'s, without error messages. -To run these tests: + If you need to test error messages or more complex evaluations, see + `lib/tests/modules.sh`, `lib/tests/sources.sh` or `lib/tests/filesystem.sh` as examples. - [nixpkgs]$ nix-instantiate --eval --strict lib/tests/misc.nix + To run these tests: -If the resulting list is empty, all tests passed. -Alternatively, to run all `lib` tests: + [nixpkgs]$ nix-instantiate --eval --strict lib/tests/misc.nix - [nixpkgs]$ nix-build lib/tests/release.nix + If the resulting list is empty, all tests passed. + Alternatively, to run all `lib` tests: + + [nixpkgs]$ nix-build lib/tests/release.nix */ let @@ -29,7 +33,7 @@ let boolToString callPackagesWith callPackageWith - cartesianProductOfSets + cartesianProduct cli composeExtensions composeManyExtensions @@ -59,17 +63,20 @@ let hasAttrByPath hasInfix id + ifilter0 isStorePath lazyDerivation + length lists listToAttrs makeExtensible + makeIncludePath makeOverridable mapAttrs + mapCartesianProduct matchAttrs mergeAttrs meta - mkOption mod nameValuePair optionalDrvAttr @@ -101,6 +108,7 @@ let types updateManyAttrsByPath versions + xor ; testingThrow = expr: { @@ -111,7 +119,6 @@ let expr = (builtins.tryEval expr).success; expected = true; }; - testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr); testSanitizeDerivationName = { name, expected }: let @@ -198,10 +205,10 @@ runTests { }; /* - testOr = { - expr = or true false; - expected = true; - }; + testOr = { + expr = or true false; + expected = true; + }; */ testAnd = { @@ -209,6 +216,21 @@ runTests { expected = false; }; + testXor = { + expr = [ + (xor true false) + (xor true true) + (xor false false) + (xor false true) + ]; + expected = [ + true + false + false + true + ]; + }; + testFix = { expr = fix (x: {a = if x ? a then "a" else "b";}); expected = {a = "a";}; @@ -296,6 +318,35 @@ runTests { expected = "a\nb\nc\n"; }; + testMakeIncludePathWithPkgs = { + expr = (makeIncludePath [ + # makeIncludePath preferably selects the "dev" output + { dev.outPath = "/dev"; out.outPath = "/out"; outPath = "/default"; } + # "out" is used if "dev" is not found + { out.outPath = "/out"; outPath = "/default"; } + # And it returns the derivation directly if there's no "out" either + { outPath = "/default"; } + # Same if the output is specified explicitly, even if there's a "dev" + { dev.outPath = "/dev"; outPath = "/default"; outputSpecified = true; } + ]); + expected = "/dev/include:/out/include:/default/include:/default/include"; + }; + + testMakeIncludePathWithEmptyList = { + expr = (makeIncludePath [ ]); + expected = ""; + }; + + testMakeIncludePathWithOneString = { + expr = (makeIncludePath [ "/usr" ]); + expected = "/usr/include"; + }; + + testMakeIncludePathWithManyString = { + expr = (makeIncludePath [ "/usr" "/usr/local" ]); + expected = "/usr/include:/usr/local/include"; + }; + testReplicateString = { expr = strings.replicate 5 "hello"; expected = "hellohellohellohellohello"; @@ -602,6 +653,31 @@ runTests { expected = ["b" "c"]; }; + testIfilter0Example = { + expr = ifilter0 (i: v: i == 0 || v > 2) [ 1 2 3 ]; + expected = [ 1 3 ]; + }; + testIfilter0Empty = { + expr = ifilter0 (i: v: abort "shouldn't be evaluated!") [ ]; + expected = [ ]; + }; + testIfilter0IndexOnly = { + expr = length (ifilter0 (i: v: mod i 2 == 0) [ (throw "0") (throw "1") (throw "2") (throw "3")]); + expected = 2; + }; + testIfilter0All = { + expr = ifilter0 (i: v: true) [ 10 11 12 13 14 15 ]; + expected = [ 10 11 12 13 14 15 ]; + }; + testIfilter0First = { + expr = ifilter0 (i: v: i == 0) [ 10 11 12 13 14 15 ]; + expected = [ 10 ]; + }; + testIfilter0Last = { + expr = ifilter0 (i: v: i == 5) [ 10 11 12 13 14 15 ]; + expected = [ 15 ]; + }; + testFold = let f = op: fold: fold op 0 (range 0 100); @@ -1267,7 +1343,7 @@ runTests { ''; }; - /* right now only invocation check */ + # right now only invocation check testToJSONSimple = let val = { foobar = [ "baz" 1 2 3 ]; @@ -1278,7 +1354,7 @@ runTests { expected = builtins.toJSON val; }; - /* right now only invocation check */ + # right now only invocation check testToYAMLSimple = let val = { list = [ { one = 1; } { two = 2; } ]; @@ -1365,7 +1441,7 @@ runTests { }; testToPrettyMultiline = { - expr = mapAttrs (const (generators.toPretty { })) rec { + expr = mapAttrs (const (generators.toPretty { })) { list = [ 3 4 [ false ] ]; attrs = { foo = null; bar.foo = "baz"; }; newlinestring = "\n"; @@ -1379,7 +1455,7 @@ runTests { there test''; }; - expected = rec { + expected = { list = '' [ 3 @@ -1417,13 +1493,10 @@ runTests { expected = "«foo»"; }; - testToPlist = - let - deriv = derivation { name = "test"; builder = "/bin/sh"; system = "aarch64-linux"; }; - in { + testToPlist = { expr = mapAttrs (const (generators.toPlist { })) { value = { - nested.values = rec { + nested.values = { int = 42; float = 0.1337; bool = true; @@ -1636,17 +1709,17 @@ runTests { }; testCartesianProductOfEmptySet = { - expr = cartesianProductOfSets {}; + expr = cartesianProduct {}; expected = [ {} ]; }; testCartesianProductOfOneSet = { - expr = cartesianProductOfSets { a = [ 1 2 3 ]; }; + expr = cartesianProduct { a = [ 1 2 3 ]; }; expected = [ { a = 1; } { a = 2; } { a = 3; } ]; }; testCartesianProductOfTwoSets = { - expr = cartesianProductOfSets { a = [ 1 ]; b = [ 10 20 ]; }; + expr = cartesianProduct { a = [ 1 ]; b = [ 10 20 ]; }; expected = [ { a = 1; b = 10; } { a = 1; b = 20; } @@ -1654,12 +1727,12 @@ runTests { }; testCartesianProductOfTwoSetsWithOneEmpty = { - expr = cartesianProductOfSets { a = [ ]; b = [ 10 20 ]; }; + expr = cartesianProduct { a = [ ]; b = [ 10 20 ]; }; expected = [ ]; }; testCartesianProductOfThreeSets = { - expr = cartesianProductOfSets { + expr = cartesianProduct { a = [ 1 2 3 ]; b = [ 10 20 30 ]; c = [ 100 200 300 ]; @@ -1703,6 +1776,30 @@ runTests { ]; }; + testMapCartesianProductOfOneSet = { + expr = mapCartesianProduct ({a}: a * 2) { a = [ 1 2 3 ]; }; + expected = [ 2 4 6 ]; + }; + + testMapCartesianProductOfTwoSets = { + expr = mapCartesianProduct ({a,b}: a + b) { a = [ 1 ]; b = [ 10 20 ]; }; + expected = [ 11 21 ]; + }; + + testMapCartesianProcutOfTwoSetsWithOneEmpty = { + expr = mapCartesianProduct (x: x.a + x.b) { a = [ ]; b = [ 10 20 ]; }; + expected = [ ]; + }; + + testMapCartesianProductOfThreeSets = { + expr = mapCartesianProduct ({a,b,c}: a + b + c) { + a = [ 1 2 3 ]; + b = [ 10 20 30 ]; + c = [ 100 200 300 ]; + }; + expected = [ 111 211 311 121 221 321 131 231 331 112 212 312 122 222 322 132 232 332 113 213 313 123 223 323 133 233 333 ]; + }; + # The example from the showAttrPath documentation testShowAttrPathExample = { expr = showAttrPath [ "foo" "10" "bar" ]; diff --git a/nixpkgs/lib/tests/modules.sh b/nixpkgs/lib/tests/modules.sh index b3bbdf9485ac..750b1d025e02 100755 --- a/nixpkgs/lib/tests/modules.sh +++ b/nixpkgs/lib/tests/modules.sh @@ -103,6 +103,18 @@ checkConfigError 'The option .sub.wrong2. does not exist. Definition values:' co checkConfigError '.*This can happen if you e.g. declared your options in .types.submodule.' config.sub ./error-mkOption-in-submodule-config.nix checkConfigError '.*A definition for option .bad. is not of type .non-empty .list of .submodule...\.' config.bad ./error-nonEmptyListOf-submodule.nix +# types.attrTag +checkConfigOutput '^true$' config.okChecks ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.syntaxError. is not of type .attribute-tagged union' config.intStrings.syntaxError ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.syntaxError2. is not of type .attribute-tagged union' config.intStrings.syntaxError2 ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.syntaxError3. is not of type .attribute-tagged union' config.intStrings.syntaxError3 ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.syntaxError4. is not of type .attribute-tagged union' config.intStrings.syntaxError4 ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.mergeError. is not of type .attribute-tagged union' config.intStrings.mergeError ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.badTagError. is not of type .attribute-tagged union' config.intStrings.badTagError ./types-attrTag.nix +checkConfigError 'A definition for option .intStrings\.badTagTypeError\.left. is not of type .signed integer.' config.intStrings.badTagTypeError.left ./types-attrTag.nix +checkConfigError 'A definition for option .nested\.right\.left. is not of type .signed integer.' config.nested.right.left ./types-attrTag.nix +checkConfigError 'In attrTag, each tag value must be an option, but tag int was a bare type, not wrapped in mkOption.' config.opt.int ./types-attrTag-wrong-decl.nix + # types.pathInStore checkConfigOutput '".*/store/0lz9p8xhf89kb1c1kk6jxrzskaiygnlh-bash-5.2-p15.drv"' config.pathInStore.ok1 ./types.nix checkConfigOutput '".*/store/0fb3ykw9r5hpayd05sr0cizwadzq1d8q-bash-5.2-p15"' config.pathInStore.ok2 ./types.nix diff --git a/nixpkgs/lib/tests/modules/doRename-condition.nix b/nixpkgs/lib/tests/modules/doRename-condition.nix index c08b3035be6f..176c21a01a17 100644 --- a/nixpkgs/lib/tests/modules/doRename-condition.nix +++ b/nixpkgs/lib/tests/modules/doRename-condition.nix @@ -1,4 +1,4 @@ -/* +/** Simulate a migration from a single-instance `services.foo` to a multi instance `services.foos.<name>` module, where `name = ""` serves as the legacy / compatibility instance. @@ -10,7 +10,7 @@ The relevant scenarios are tested in separate files: - ./doRename-condition-enable.nix - ./doRename-condition-no-enable.nix - */ +*/ { config, lib, ... }: let inherit (lib) mkOption mkEnableOption types doRename; diff --git a/nixpkgs/lib/tests/modules/docs.nix b/nixpkgs/lib/tests/modules/docs.nix new file mode 100644 index 000000000000..225aa7eac1de --- /dev/null +++ b/nixpkgs/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/nixpkgs/lib/tests/modules/types-attrTag-wrong-decl.nix b/nixpkgs/lib/tests/modules/types-attrTag-wrong-decl.nix new file mode 100644 index 000000000000..d03370bc10da --- /dev/null +++ b/nixpkgs/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/nixpkgs/lib/tests/modules/types-attrTag.nix b/nixpkgs/lib/tests/modules/types-attrTag.nix new file mode 100644 index 000000000000..b2e5158bb44b --- /dev/null +++ b/nixpkgs/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); + }; +} diff --git a/nixpkgs/lib/tests/release.nix b/nixpkgs/lib/tests/release.nix index 5b2a9df1635c..1447e8817091 100644 --- a/nixpkgs/lib/tests/release.nix +++ b/nixpkgs/lib/tests/release.nix @@ -2,7 +2,7 @@ # Don't test properties of pkgs.lib, but rather the lib in the parent directory pkgs ? import ../.. {} // { lib = throw "pkgs.lib accessed, but the lib tests should use nixpkgs' lib path directly!"; }, nix ? pkgs-nixVersions.stable, - nixVersions ? [ pkgs-nixVersions.minimum nix pkgs-nixVersions.unstable ], + nixVersions ? [ pkgs-nixVersions.minimum nix pkgs-nixVersions.latest ], pkgs-nixVersions ? import ./nix-for-tests.nix { inherit pkgs; }, }: diff --git a/nixpkgs/lib/tests/systems.nix b/nixpkgs/lib/tests/systems.nix index e142ff307fbd..03c5d6868962 100644 --- a/nixpkgs/lib/tests/systems.nix +++ b/nixpkgs/lib/tests/systems.nix @@ -40,7 +40,7 @@ lib.runTests ( testarm = mseteq arm [ "armv5tel-linux" "armv6l-linux" "armv6l-netbsd" "armv6l-none" "armv7a-linux" "armv7a-netbsd" "armv7l-linux" "armv7l-netbsd" "arm-none" "armv7a-darwin" ]; testarmv7 = mseteq armv7 [ "armv7a-darwin" "armv7a-linux" "armv7l-linux" "armv7a-netbsd" "armv7l-netbsd" ]; - testi686 = mseteq i686 [ "i686-linux" "i686-freebsd13" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ]; + testi686 = mseteq i686 [ "i686-linux" "i686-freebsd" "i686-genode" "i686-netbsd" "i686-openbsd" "i686-cygwin" "i686-windows" "i686-none" "i686-darwin" ]; testmips = mseteq mips [ "mips-none" "mips64-none" "mips-linux" "mips64-linux" "mips64el-linux" "mipsel-linux" "mipsel-netbsd" ]; testmmix = mseteq mmix [ "mmix-mmixware" ]; testpower = mseteq power [ "powerpc-netbsd" "powerpc-none" "powerpc64-linux" "powerpc64le-linux" "powerpcle-none" ]; @@ -48,11 +48,11 @@ lib.runTests ( testriscv32 = mseteq riscv32 [ "riscv32-linux" "riscv32-netbsd" "riscv32-none" ]; testriscv64 = mseteq riscv64 [ "riscv64-linux" "riscv64-netbsd" "riscv64-none" ]; tests390x = mseteq s390x [ "s390x-linux" "s390x-none" ]; - testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd13" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ]; + testx86_64 = mseteq x86_64 [ "x86_64-linux" "x86_64-darwin" "x86_64-freebsd" "x86_64-genode" "x86_64-redox" "x86_64-openbsd" "x86_64-netbsd" "x86_64-cygwin" "x86_64-solaris" "x86_64-windows" "x86_64-none" ]; testcygwin = mseteq cygwin [ "i686-cygwin" "x86_64-cygwin" ]; testdarwin = mseteq darwin [ "x86_64-darwin" "i686-darwin" "aarch64-darwin" "armv7a-darwin" ]; - testfreebsd = mseteq freebsd [ "i686-freebsd13" "x86_64-freebsd13" ]; + testfreebsd = mseteq freebsd [ "i686-freebsd" "x86_64-freebsd" ]; testgenode = mseteq genode [ "aarch64-genode" "i686-genode" "x86_64-genode" ]; testredox = mseteq redox [ "x86_64-redox" ]; testgnu = mseteq gnu (linux /* ++ kfreebsd ++ ... */); |