2 # nix-instantiate --eval --strict nixpkgs/lib/tests/misc.nix
3 # if the resulting list is empty, all tests passed
4 with import ../default.nix;
8 testSanitizeDerivationName = { name, expected }:
11 name = strings.sanitizeDerivationName name;
16 # Evaluate the derivation so an invalid name would be caught
17 expr = builtins.seq drv.drvPath drv.name;
39 (x: x + 2) # 2 + 2 = 4
40 (x: x * 2) # 4 * 2 = 8
70 expr = and true false;
75 expr = fix (x: {a = if x ? a then "a" else "b";});
76 expected = {a = "a";};
79 testComposeExtensions = {
80 expr = let obj = makeExtensible (self: { foo = self.bar; });
81 f = self: super: { bar = false; baz = true; };
82 g = self: super: { bar = super.baz or false; };
83 f_o_g = composeExtensions f g;
84 composed = obj.extend f_o_g;
89 testComposeManyExtensions0 = {
90 expr = let obj = makeExtensible (self: { foo = true; });
91 emptyComposition = composeManyExtensions [];
92 composed = obj.extend emptyComposition;
97 testComposeManyExtensions =
98 let f = self: super: { bar = false; baz = true; };
99 g = self: super: { bar = super.baz or false; };
100 h = self: super: { qux = super.bar or false; };
101 obj = makeExtensible (self: { foo = self.qux; });
103 expr = let composition = composeManyExtensions [f g h];
104 composed = obj.extend composition;
106 expected = (obj.extend (composeExtensions f (composeExtensions g h))).foo;
110 expr = (bitAnd 3 10);
120 expr = (bitXor 3 10);
125 expr = toHexString 250;
130 expr = toBaseDigits 2 6;
131 expected = [ 1 1 0 ];
134 testFunctionArgsFunctor = {
135 expr = functionArgs { __functor = self: { a, b }: null; };
136 expected = { a = false; b = false; };
139 testFunctionArgsSetFunctionArgs = {
140 expr = functionArgs (setFunctionArgs (args: args.x) { x = false; });
141 expected = { x = false; };
146 testConcatMapStrings = {
147 expr = concatMapStrings (x: x + ";") ["a" "b" "c"];
151 testConcatStringsSep = {
152 expr = concatStringsSep "," ["a" "b" "c"];
156 testSplitStringsSimple = {
157 expr = strings.splitString "." "a.b.c.d";
158 expected = [ "a" "b" "c" "d" ];
161 testSplitStringsEmpty = {
162 expr = strings.splitString "." "a..b";
163 expected = [ "a" "" "b" ];
166 testSplitStringsOne = {
167 expr = strings.splitString ":" "a.b";
168 expected = [ "a.b" ];
171 testSplitStringsNone = {
172 expr = strings.splitString "." "";
176 testSplitStringsFirstEmpty = {
177 expr = strings.splitString "/" "/a/b/c";
178 expected = [ "" "a" "b" "c" ];
181 testSplitStringsLastEmpty = {
182 expr = strings.splitString ":" "2001:db8:0:0042::8a2e:370:";
183 expected = [ "2001" "db8" "0" "0042" "" "8a2e" "370" "" ];
186 testSplitStringsRegex = {
187 expr = strings.splitString "\\[{}]()^$?*+|." "A\\[{}]()^$?*+|.B";
188 expected = [ "A" "B" ];
191 testSplitStringsDerivation = {
192 expr = take 3 (strings.splitString "/" (derivation {
197 expected = ["" "nix" "store"];
200 testSplitVersionSingle = {
201 expr = versions.splitVersion "1";
205 testSplitVersionDouble = {
206 expr = versions.splitVersion "1.2";
207 expected = [ "1" "2" ];
210 testSplitVersionTriple = {
211 expr = versions.splitVersion "1.2.3";
212 expected = [ "1" "2" "3" ];
218 "${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11";
220 storePath = isStorePath goodPath;
221 storePathDerivation = isStorePath (import ../.. { system = "x86_64-linux"; }).hello;
222 storePathAppendix = isStorePath
223 "${goodPath}/bin/python";
224 nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath)));
225 asPath = isStorePath (/. + goodPath);
226 otherPath = isStorePath "/something/else";
228 attrset = isStorePath {};
229 list = isStorePath [];
230 int = isStorePath 42;
235 storePathDerivation = true;
236 storePathAppendix = false;
249 expr = escapeXML ''"test" 'test' < & >'';
250 expected = ""test" 'test' < & >";
256 STRing01 = "just a 'string'";
257 _array_ = [ "with" "more strings" ];
258 assoc."with some" = ''
264 foo = "ignored attribute";
268 __toString = _: "hello toString";
269 bar = "ignored attribute";
274 STRing01='just a '\'''string'\''''
275 declare -a _array_=('with' 'more strings')
276 declare -A assoc=(['with some']='strings
281 stringable='hello toString'
285 testHasInfixFalse = {
286 expr = hasInfix "c" "abde";
291 expr = hasInfix "c" "abcde";
295 testHasInfixDerivation = {
296 expr = hasInfix "hello" (import ../.. { system = "x86_64-linux"; }).hello;
301 expr = hasInfix "tests" ./.;
305 testHasInfixPathStoreDir = {
306 expr = hasInfix builtins.storeDir ./.;
310 testHasInfixToString = {
311 expr = hasInfix "a" { __toString = _: "a"; };
315 testNormalizePath = {
316 expr = strings.normalizePath "//a/b//c////d/";
317 expected = "/a/b/c/d/";
321 expr = strings.charToInt "A";
326 expr = strings.escapeC [ " " ] "Hello World";
327 expected = "Hello\\x20World";
330 testToInt = testAllTrue [
335 (123 == toInt " 123")
336 (123 == toInt "123 ")
337 (123 == toInt " 123 ")
338 (123 == toInt " 123 ")
344 testToIntFails = testAllTrue [
345 ( builtins.tryEval (toInt "") == { success = false; value = false; } )
346 ( builtins.tryEval (toInt "123 123") == { success = false; value = false; } )
347 ( builtins.tryEval (toInt "0 123") == { success = false; value = false; } )
348 ( builtins.tryEval (toInt " 0d ") == { success = false; value = false; } )
349 ( builtins.tryEval (toInt " 1d ") == { success = false; value = false; } )
350 ( builtins.tryEval (toInt " d0 ") == { success = false; value = false; } )
351 ( builtins.tryEval (toInt "00") == { success = false; value = false; } )
352 ( builtins.tryEval (toInt "01") == { success = false; value = false; } )
353 ( builtins.tryEval (toInt "002") == { success = false; value = false; } )
354 ( builtins.tryEval (toInt " 002 ") == { success = false; value = false; } )
355 ( builtins.tryEval (toInt " foo ") == { success = false; value = false; } )
356 ( builtins.tryEval (toInt " foo 123 ") == { success = false; value = false; } )
357 ( builtins.tryEval (toInt " foo123 ") == { success = false; value = false; } )
360 testToIntBase10 = testAllTrue [
362 (123 == toIntBase10 "123")
363 (0 == toIntBase10 "0")
365 (123 == toIntBase10 " 123")
366 (123 == toIntBase10 "123 ")
367 (123 == toIntBase10 " 123 ")
368 (123 == toIntBase10 " 123 ")
369 (0 == toIntBase10 " 0")
370 (0 == toIntBase10 "0 ")
371 (0 == toIntBase10 " 0 ")
373 (123 == toIntBase10 "0123")
374 (123 == toIntBase10 "0000123")
375 (0 == toIntBase10 "000000")
376 # Whitespace and Zero Padding
377 (123 == toIntBase10 " 0123")
378 (123 == toIntBase10 "0123 ")
379 (123 == toIntBase10 " 0123 ")
380 (123 == toIntBase10 " 0000123")
381 (123 == toIntBase10 "0000123 ")
382 (123 == toIntBase10 " 0000123 ")
383 (0 == toIntBase10 " 000000")
384 (0 == toIntBase10 "000000 ")
385 (0 == toIntBase10 " 000000 ")
388 testToIntBase10Fails = testAllTrue [
389 ( builtins.tryEval (toIntBase10 "") == { success = false; value = false; } )
390 ( builtins.tryEval (toIntBase10 "123 123") == { success = false; value = false; } )
391 ( builtins.tryEval (toIntBase10 "0 123") == { success = false; value = false; } )
392 ( builtins.tryEval (toIntBase10 " 0d ") == { success = false; value = false; } )
393 ( builtins.tryEval (toIntBase10 " 1d ") == { success = false; value = false; } )
394 ( builtins.tryEval (toIntBase10 " d0 ") == { success = false; value = false; } )
395 ( builtins.tryEval (toIntBase10 " foo ") == { success = false; value = false; } )
396 ( builtins.tryEval (toIntBase10 " foo 123 ") == { success = false; value = false; } )
397 ( builtins.tryEval (toIntBase10 " foo 00123 ") == { success = false; value = false; } )
398 ( builtins.tryEval (toIntBase10 " foo00123 ") == { success = false; value = false; } )
404 expr = filter (x: x != "a") ["a" "b" "c" "a"];
405 expected = ["b" "c"];
410 f = op: fold: fold op 0 (range 0 100);
411 # fold with associative operator
412 assoc = f builtins.add;
413 # fold with non-associative operator
414 nonAssoc = f builtins.sub;
417 assocRight = assoc foldr;
418 # right fold with assoc operator is same as left fold
419 assocRightIsLeft = assoc foldr == assoc foldl;
420 nonAssocRight = nonAssoc foldr;
421 nonAssocLeft = nonAssoc foldl;
422 # with non-assoc operator the fold results are not the same
423 nonAssocRightIsNotLeft = nonAssoc foldl != nonAssoc foldr;
424 # fold is an alias for foldr
425 foldIsRight = nonAssoc fold == nonAssoc foldr;
429 assocRightIsLeft = true;
431 nonAssocLeft = (-5050);
432 nonAssocRightIsNotLeft = true;
437 testTake = testAllTrue [
438 ([] == (take 0 [ 1 2 3 ]))
439 ([1] == (take 1 [ 1 2 3 ]))
440 ([ 1 2 ] == (take 2 [ 1 2 3 ]))
441 ([ 1 2 3 ] == (take 3 [ 1 2 3 ]))
442 ([ 1 2 3 ] == (take 4 [ 1 2 3 ]))
446 expr = foldAttrs (n: a: [n] ++ a) [] [
450 expected = { a = [ 2 3 ]; b = [7]; c = [8];};
454 expr = sort builtins.lessThan [ 40 2 30 42 ];
455 expected = [2 30 40 42];
458 testToIntShouldConvertStringToInt = {
463 testToIntShouldThrowErrorIfItCouldNotConvertToInt = {
464 expr = builtins.tryEval (toInt "\"foo\"");
465 expected = { success = false; value = false; };
468 testHasAttrByPathTrue = {
469 expr = hasAttrByPath ["a" "b"] { a = { b = "yey"; }; };
473 testHasAttrByPathFalse = {
474 expr = hasAttrByPath ["a" "b"] { a = { c = "yey"; }; };
481 # code from the example
482 testRecursiveUpdateUntil = {
483 expr = recursiveUpdateUntil (path: l: r: path == ["foo"]) {
484 # first attribute set
489 #second attribute set
495 foo.bar = 1; # 'foo.*' from the second set
497 bar = 3; # 'bar' from the first set
498 baz = 4; # 'baz' from the second set
502 testOverrideExistingEmpty = {
503 expr = overrideExisting {} { a = 1; };
507 testOverrideExistingDisjoint = {
508 expr = overrideExisting { b = 2; } { a = 1; };
509 expected = { b = 2; };
512 testOverrideExistingOverride = {
513 expr = overrideExisting { a = 3; b = 2; } { a = 1; };
514 expected = { a = 1; b = 2; };
518 # these tests assume attributes are converted to lists
519 # in alphabetical order
521 testMkKeyValueDefault = {
522 expr = generators.mkKeyValueDefault {} ":" "f:oo" "bar";
523 expected = ''f\:oo:bar'';
526 testMkValueString = {
534 # float = 42.23; # floats are strange
537 (const (generators.mkValueStringDefault {}))
545 # float = "42.23" true false [ "bar" ] ]'';
550 expr = generators.toKeyValue {} {
561 expr = generators.toINI {} {};
565 testToINIEmptySection = {
566 expr = generators.toINI {} { foo = {}; bar = {}; };
574 testToINIDuplicateKeys = {
575 expr = generators.toINI { listsAsDuplicateKeys = true; } { foo.bar = true; baz.qux = [ 1 false ]; };
586 testToINIDefaultEscapes = {
587 expr = generators.toINI {} {
588 "no [ and ] allowed unescaped" = {
589 "and also no = in keys" = 42;
593 [no \[ and \] allowed unescaped]
594 and also no \= in keys=42
598 testToINIDefaultFull = {
599 expr = generators.toINI {} {
602 x = "Me-se JarJar Binx";
603 # booleans are converted verbatim by default
607 "he\\h=he" = "this is okay";
612 he\h\=he=this is okay
621 testToINIWithGlobalSectionEmpty = {
622 expr = generators.toINIWithGlobalSection {} {
632 testToINIWithGlobalSectionGlobalEmptyIsTheSameAsToINI =
637 x = "Me-se JarJar Binx";
640 "he\\h=he" = "this is okay";
645 generators.toINIWithGlobalSection {} {
649 expected = generators.toINI {} sections;
652 testToINIWithGlobalSectionFull = {
653 expr = generators.toINIWithGlobalSection {} {
661 x = "Me-se JarJar Binx";
664 "he\\h=he" = "this is okay";
673 he\h\=he=this is okay
681 /* right now only invocation check */
684 foobar = [ "baz" 1 2 3 ];
687 expr = generators.toJSON {} val;
688 # trivial implementation
689 expected = builtins.toJSON val;
692 /* right now only invocation check */
695 list = [ { one = 1; } { two = 2; } ];
699 expr = generators.toYAML {} val;
700 # trivial implementation
701 expected = builtins.toJSON val;
706 deriv = derivation { name = "test"; builder = "/bin/sh"; system = "aarch64-linux"; };
708 expr = mapAttrs (const (generators.toPretty { multiline = false; })) rec {
714 newlinestring = "\n";
718 functionArgs = { arg ? 4, foo }: arg;
719 list = [ 3 4 function [ false ] ];
721 attrs = { foo = null; "foo bar" = "baz"; };
729 emptystring = ''""'';
730 string = ''"fno\"rd"'';
731 newlinestring = "\"\\n\"";
734 function = "<function>";
735 functionArgs = "<function, args: {arg?, foo}>";
736 list = "[ 3 4 ${function} [ false ] ]";
738 attrs = "{ foo = null; \"foo bar\" = \"baz\"; }";
740 drv = "<derivation ${deriv.drvPath}>";
749 expr = generators.toPretty { } (generators.withRecursion { throwOnDepthLimit = false; depthLimit = 2; } a);
750 expected = "{\n b = 1;\n c = {\n b = \"<unevaluated>\";\n c = {\n b = \"<unevaluated>\";\n c = \"<unevaluated>\";\n };\n };\n}";
753 testToPrettyLimitThrow =
758 expr = (builtins.tryEval
759 (generators.toPretty { } (generators.withRecursion { depthLimit = 2; } a))).success;
763 testWithRecursionDealsWithFunctors =
766 __functor = self: { a, b, }: null;
774 expr = generators.toPretty { } (generators.withRecursion { depthLimit = 1; throwOnDepthLimit = false; } a);
775 expected = "{\n b = <function, args: {a, b}>;\n c = {\n d = \"<unevaluated>\";\n };\n value = \"<unevaluated>\";\n}";
778 testToPrettyMultiline = {
779 expr = mapAttrs (const (generators.toPretty { })) rec {
780 list = [ 3 4 [ false ] ];
781 attrs = { foo = null; bar.foo = "baz"; };
782 newlinestring = "\n";
788 multilinestring' = ''
809 newlinestring = "''\n \n''";
816 multilinestring' = ''
825 testToPrettyAllowPrettyValues = {
826 expr = generators.toPretty { allowPrettyValues = true; }
827 { __pretty = v: "«" + v + "»"; val = "foo"; };
828 expected = "«foo»";
834 testToGNUCommandLine = {
835 expr = cli.toGNUCommandLine {} {
836 data = builtins.toJSON { id = 0; };
840 url = [ "https://example.com/foo" "https://example.com/bar" ];
847 "--data" "{\"id\":0}"
849 "--url" "https://example.com/foo"
850 "--url" "https://example.com/bar"
855 testToGNUCommandLineShell = {
856 expr = cli.toGNUCommandLineShell {} {
857 data = builtins.toJSON { id = 0; };
861 url = [ "https://example.com/foo" "https://example.com/bar" ];
866 expected = "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'";
869 testSanitizeDerivationNameLeadingDots = testSanitizeDerivationName {
874 testSanitizeDerivationNameUnicode = testSanitizeDerivationName {
879 testSanitizeDerivationNameAscii = testSanitizeDerivationName {
880 name = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
881 expected = "-+--.-0123456789-=-?-ABCDEFGHIJKLMNOPQRSTUVWXYZ-_-abcdefghijklmnopqrstuvwxyz-";
884 testSanitizeDerivationNameTooLong = testSanitizeDerivationName {
885 name = "This string is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong";
886 expected = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong";
889 testSanitizeDerivationNameTooLongWithInvalid = testSanitizeDerivationName {
890 name = "Hello there aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&&&&&&&";
891 expected = "there-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-";
894 testSanitizeDerivationNameEmpty = testSanitizeDerivationName {
896 expected = "unknown";
899 testFreeformOptions = {
902 submodule = { lib, ... }: {
903 freeformType = lib.types.attrsOf (lib.types.submodule {
904 options.bar = lib.mkOption {};
906 options.bar = lib.mkOption {};
909 module = { lib, ... }: {
910 options.foo = lib.mkOption {
911 type = lib.types.submodule submodule;
915 options = (evalModules {
916 modules = [ module ];
919 locs = filter (o: ! o.internal) (optionAttrSetToDocList options);
920 in map (o: o.loc) locs;
921 expected = [ [ "_module" "args" ] [ "foo" ] [ "foo" "<name>" "bar" ] [ "foo" "bar" ] ];
924 testCartesianProductOfEmptySet = {
925 expr = cartesianProductOfSets {};
929 testCartesianProductOfOneSet = {
930 expr = cartesianProductOfSets { a = [ 1 2 3 ]; };
931 expected = [ { a = 1; } { a = 2; } { a = 3; } ];
934 testCartesianProductOfTwoSets = {
935 expr = cartesianProductOfSets { a = [ 1 ]; b = [ 10 20 ]; };
942 testCartesianProductOfTwoSetsWithOneEmpty = {
943 expr = cartesianProductOfSets { a = [ ]; b = [ 10 20 ]; };
947 testCartesianProductOfThreeSets = {
948 expr = cartesianProductOfSets {
954 { a = 1; b = 10; c = 100; }
955 { a = 1; b = 10; c = 200; }
956 { a = 1; b = 10; c = 300; }
958 { a = 1; b = 20; c = 100; }
959 { a = 1; b = 20; c = 200; }
960 { a = 1; b = 20; c = 300; }
962 { a = 1; b = 30; c = 100; }
963 { a = 1; b = 30; c = 200; }
964 { a = 1; b = 30; c = 300; }
966 { a = 2; b = 10; c = 100; }
967 { a = 2; b = 10; c = 200; }
968 { a = 2; b = 10; c = 300; }
970 { a = 2; b = 20; c = 100; }
971 { a = 2; b = 20; c = 200; }
972 { a = 2; b = 20; c = 300; }
974 { a = 2; b = 30; c = 100; }
975 { a = 2; b = 30; c = 200; }
976 { a = 2; b = 30; c = 300; }
978 { a = 3; b = 10; c = 100; }
979 { a = 3; b = 10; c = 200; }
980 { a = 3; b = 10; c = 300; }
982 { a = 3; b = 20; c = 100; }
983 { a = 3; b = 20; c = 200; }
984 { a = 3; b = 20; c = 300; }
986 { a = 3; b = 30; c = 100; }
987 { a = 3; b = 30; c = 200; }
988 { a = 3; b = 30; c = 300; }
992 # The example from the showAttrPath documentation
993 testShowAttrPathExample = {
994 expr = showAttrPath [ "foo" "10" "bar" ];
995 expected = "foo.\"10\".bar";
998 testShowAttrPathEmpty = {
999 expr = showAttrPath [];
1000 expected = "<root attribute path>";
1003 testShowAttrPathVarious = {
1004 expr = showAttrPath [
1011 expected = ''".".foo."2".a2-b._bc'de'';
1015 expr = groupBy (n: toString (mod n 5)) (range 0 16);
1017 "0" = [ 0 5 10 15 ];
1018 "1" = [ 1 6 11 16 ];
1026 expr = groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ];
1027 expected = { false = 3; true = 12; };
1030 # The example from the updateManyAttrsByPath documentation
1031 testUpdateManyAttrsByPathExample = {
1032 expr = updateManyAttrsByPath [
1035 update = old: { d = old.c; };
1038 path = [ "a" "b" "c" ];
1039 update = old: old + 1;
1046 expected = { a = { b = { d = 1; }; }; x = { y = "xy"; }; };
1049 # If there are no updates, the value is passed through
1050 testUpdateManyAttrsByPathNone = {
1051 expr = updateManyAttrsByPath [] "something";
1052 expected = "something";
1055 # A single update to the root path is just like applying the function directly
1056 testUpdateManyAttrsByPathSingleIncrement = {
1057 expr = updateManyAttrsByPath [
1060 update = old: old + 1;
1066 # Multiple updates can be applied are done in order
1067 testUpdateManyAttrsByPathMultipleIncrements = {
1068 expr = updateManyAttrsByPath [
1071 update = old: old + "a";
1075 update = old: old + "b";
1079 update = old: old + "c";
1085 # If an update doesn't use the value, all previous updates are not evaluated
1086 testUpdateManyAttrsByPathLazy = {
1087 expr = updateManyAttrsByPath [
1090 update = old: old + throw "nope";
1094 update = old: "untainted";
1097 expected = "untainted";
1100 # Deeply nested attributes can be updated without affecting others
1101 testUpdateManyAttrsByPathDeep = {
1102 expr = updateManyAttrsByPath [
1104 path = [ "a" "b" "c" ];
1105 update = old: old + 1;
1123 # Nested attributes are updated first
1124 testUpdateManyAttrsByPathNestedBeforehand = {
1125 expr = updateManyAttrsByPath [
1128 update = old: old // { x = old.b; };
1132 update = old: old + 1;
1143 ## Levenshtein distance functions and co.
1144 testCommonPrefixLengthEmpty = {
1145 expr = strings.commonPrefixLength "" "hello";
1149 testCommonPrefixLengthSame = {
1150 expr = strings.commonPrefixLength "hello" "hello";
1154 testCommonPrefixLengthDiffering = {
1155 expr = strings.commonPrefixLength "hello" "hey";
1159 testCommonSuffixLengthEmpty = {
1160 expr = strings.commonSuffixLength "" "hello";
1164 testCommonSuffixLengthSame = {
1165 expr = strings.commonSuffixLength "hello" "hello";
1169 testCommonSuffixLengthDiffering = {
1170 expr = strings.commonSuffixLength "test" "rest";
1174 testLevenshteinEmpty = {
1175 expr = strings.levenshtein "" "";
1179 testLevenshteinOnlyAdd = {
1180 expr = strings.levenshtein "" "hello there";
1184 testLevenshteinOnlyRemove = {
1185 expr = strings.levenshtein "hello there" "";
1189 testLevenshteinOnlyTransform = {
1190 expr = strings.levenshtein "abcdef" "ghijkl";
1194 testLevenshteinMixed = {
1195 expr = strings.levenshtein "kitchen" "sitting";
1199 testLevenshteinAtMostZeroFalse = {
1200 expr = strings.levenshteinAtMost 0 "foo" "boo";
1204 testLevenshteinAtMostZeroTrue = {
1205 expr = strings.levenshteinAtMost 0 "foo" "foo";
1209 testLevenshteinAtMostOneFalse = {
1210 expr = strings.levenshteinAtMost 1 "car" "ct";
1214 testLevenshteinAtMostOneTrue = {
1215 expr = strings.levenshteinAtMost 1 "car" "cr";
1219 # We test levenshteinAtMost 2 particularly well because it uses a complicated
1221 testLevenshteinAtMostTwoIsEmpty = {
1222 expr = strings.levenshteinAtMost 2 "" "";
1226 testLevenshteinAtMostTwoIsZero = {
1227 expr = strings.levenshteinAtMost 2 "abcdef" "abcdef";
1231 testLevenshteinAtMostTwoIsOne = {
1232 expr = strings.levenshteinAtMost 2 "abcdef" "abddef";
1236 testLevenshteinAtMostTwoDiff0False = {
1237 expr = strings.levenshteinAtMost 2 "abcdef" "aczyef";
1241 testLevenshteinAtMostTwoDiff0Outer = {
1242 expr = strings.levenshteinAtMost 2 "abcdef" "zbcdez";
1246 testLevenshteinAtMostTwoDiff0DelLeft = {
1247 expr = strings.levenshteinAtMost 2 "abcdef" "bcdefz";
1251 testLevenshteinAtMostTwoDiff0DelRight = {
1252 expr = strings.levenshteinAtMost 2 "abcdef" "zabcde";
1256 testLevenshteinAtMostTwoDiff1False = {
1257 expr = strings.levenshteinAtMost 2 "abcdef" "bddez";
1261 testLevenshteinAtMostTwoDiff1DelLeft = {
1262 expr = strings.levenshteinAtMost 2 "abcdef" "bcdez";
1266 testLevenshteinAtMostTwoDiff1DelRight = {
1267 expr = strings.levenshteinAtMost 2 "abcdef" "zbcde";
1271 testLevenshteinAtMostTwoDiff2False = {
1272 expr = strings.levenshteinAtMost 2 "hello" "hxo";
1276 testLevenshteinAtMostTwoDiff2True = {
1277 expr = strings.levenshteinAtMost 2 "hello" "heo";
1281 testLevenshteinAtMostTwoDiff3 = {
1282 expr = strings.levenshteinAtMost 2 "hello" "ho";
1286 testLevenshteinAtMostThreeFalse = {
1287 expr = strings.levenshteinAtMost 3 "hello" "Holla!";
1291 testLevenshteinAtMostThreeTrue = {
1292 expr = strings.levenshteinAtMost 3 "hello" "Holla";
1298 testLazyDerivationIsLazyInDerivationForAttrNames = {
1299 expr = attrNames (lazyDerivation {
1300 derivation = throw "not lazy enough";
1302 # It's ok to add attribute names here when lazyDerivation is improved
1303 # in accordance with its inline comments.
1304 expected = [ "drvPath" "meta" "name" "out" "outPath" "outputName" "outputs" "system" "type" ];
1307 testLazyDerivationIsLazyInDerivationForPassthruAttr = {
1308 expr = (lazyDerivation {
1309 derivation = throw "not lazy enough";
1310 passthru.tests = "whatever is in tests";
1312 expected = "whatever is in tests";
1315 testLazyDerivationIsLazyInDerivationForPassthruAttr2 = {
1316 # passthru.tests is not a special case. It works for any attr.
1317 expr = (lazyDerivation {
1318 derivation = throw "not lazy enough";
1319 passthru.foo = "whatever is in foo";
1321 expected = "whatever is in foo";
1324 testLazyDerivationIsLazyInDerivationForMeta = {
1325 expr = (lazyDerivation {
1326 derivation = throw "not lazy enough";
1327 meta = "whatever is in meta";
1329 expected = "whatever is in meta";
1332 testLazyDerivationReturnsDerivationAttrs = let
1334 type = "derivation";
1337 outPath = "test outPath";
1339 drvPath = "test drvPath";
1341 system = "test system";
1345 expr = lazyDerivation { inherit derivation; };
1346 expected = derivation;
1349 testTypeDescriptionInt = {
1350 expr = (with types; int).description;
1351 expected = "signed integer";
1353 testTypeDescriptionListOfInt = {
1354 expr = (with types; listOf int).description;
1355 expected = "list of signed integer";
1357 testTypeDescriptionListOfListOfInt = {
1358 expr = (with types; listOf (listOf int)).description;
1359 expected = "list of list of signed integer";
1361 testTypeDescriptionListOfEitherStrOrBool = {
1362 expr = (with types; listOf (either str bool)).description;
1363 expected = "list of (string or boolean)";
1365 testTypeDescriptionEitherListOfStrOrBool = {
1366 expr = (with types; either (listOf bool) str).description;
1367 expected = "(list of boolean) or string";
1369 testTypeDescriptionEitherStrOrListOfBool = {
1370 expr = (with types; either str (listOf bool)).description;
1371 expected = "string or list of boolean";
1373 testTypeDescriptionOneOfListOfStrOrBool = {
1374 expr = (with types; oneOf [ (listOf bool) str ]).description;
1375 expected = "(list of boolean) or string";
1377 testTypeDescriptionOneOfListOfStrOrBoolOrNumber = {
1378 expr = (with types; oneOf [ (listOf bool) str number ]).description;
1379 expected = "(list of boolean) or string or signed integer or floating point number";
1381 testTypeDescriptionEitherListOfBoolOrEitherStringOrNumber = {
1382 expr = (with types; either (listOf bool) (either str number)).description;
1383 expected = "(list of boolean) or string or signed integer or floating point number";
1385 testTypeDescriptionEitherEitherListOfBoolOrStringOrNumber = {
1386 expr = (with types; either (either (listOf bool) str) number).description;
1387 expected = "(list of boolean) or string or signed integer or floating point number";
1389 testTypeDescriptionEitherNullOrBoolOrString = {
1390 expr = (with types; either (nullOr bool) str).description;
1391 expected = "null or boolean or string";
1393 testTypeDescriptionEitherListOfEitherBoolOrStrOrInt = {
1394 expr = (with types; either (listOf (either bool str)) int).description;
1395 expected = "(list of (boolean or string)) or signed integer";
1397 testTypeDescriptionEitherIntOrListOrEitherBoolOrStr = {
1398 expr = (with types; either int (listOf (either bool str))).description;
1399 expected = "signed integer or list of (boolean or string)";