at 18.09-beta 10 kB view raw
1# to run these tests: 2# nix-instantiate --eval --strict nixpkgs/lib/tests/misc.nix 3# if the resulting list is empty, all tests passed 4with import ../default.nix; 5 6runTests { 7 8 9# TRIVIAL 10 11 testId = { 12 expr = id 1; 13 expected = 1; 14 }; 15 16 testConst = { 17 expr = const 2 3; 18 expected = 2; 19 }; 20 21 /* 22 testOr = { 23 expr = or true false; 24 expected = true; 25 }; 26 */ 27 28 testAnd = { 29 expr = and true false; 30 expected = false; 31 }; 32 33 testFix = { 34 expr = fix (x: {a = if x ? a then "a" else "b";}); 35 expected = {a = "a";}; 36 }; 37 38 testComposeExtensions = { 39 expr = let obj = makeExtensible (self: { foo = self.bar; }); 40 f = self: super: { bar = false; baz = true; }; 41 g = self: super: { bar = super.baz or false; }; 42 f_o_g = composeExtensions f g; 43 composed = obj.extend f_o_g; 44 in composed.foo; 45 expected = true; 46 }; 47 48 testBitAnd = { 49 expr = (bitAnd 3 10); 50 expected = 2; 51 }; 52 53 testBitOr = { 54 expr = (bitOr 3 10); 55 expected = 11; 56 }; 57 58 testBitXor = { 59 expr = (bitXor 3 10); 60 expected = 9; 61 }; 62 63# STRINGS 64 65 testConcatMapStrings = { 66 expr = concatMapStrings (x: x + ";") ["a" "b" "c"]; 67 expected = "a;b;c;"; 68 }; 69 70 testConcatStringsSep = { 71 expr = concatStringsSep "," ["a" "b" "c"]; 72 expected = "a,b,c"; 73 }; 74 75 testSplitStringsSimple = { 76 expr = strings.splitString "." "a.b.c.d"; 77 expected = [ "a" "b" "c" "d" ]; 78 }; 79 80 testSplitStringsEmpty = { 81 expr = strings.splitString "." "a..b"; 82 expected = [ "a" "" "b" ]; 83 }; 84 85 testSplitStringsOne = { 86 expr = strings.splitString ":" "a.b"; 87 expected = [ "a.b" ]; 88 }; 89 90 testSplitStringsNone = { 91 expr = strings.splitString "." ""; 92 expected = [ "" ]; 93 }; 94 95 testSplitStringsFirstEmpty = { 96 expr = strings.splitString "/" "/a/b/c"; 97 expected = [ "" "a" "b" "c" ]; 98 }; 99 100 testSplitStringsLastEmpty = { 101 expr = strings.splitString ":" "2001:db8:0:0042::8a2e:370:"; 102 expected = [ "2001" "db8" "0" "0042" "" "8a2e" "370" "" ]; 103 }; 104 105 testIsStorePath = { 106 expr = 107 let goodPath = 108 "${builtins.storeDir}/d945ibfx9x185xf04b890y4f9g3cbb63-python-2.7.11"; 109 in { 110 storePath = isStorePath goodPath; 111 storePathDerivation = isStorePath (import ../.. {}).hello; 112 storePathAppendix = isStorePath 113 "${goodPath}/bin/python"; 114 nonAbsolute = isStorePath (concatStrings (tail (stringToCharacters goodPath))); 115 asPath = isStorePath (builtins.toPath goodPath); 116 otherPath = isStorePath "/something/else"; 117 otherVals = { 118 attrset = isStorePath {}; 119 list = isStorePath []; 120 int = isStorePath 42; 121 }; 122 }; 123 expected = { 124 storePath = true; 125 storePathDerivation = true; 126 storePathAppendix = false; 127 nonAbsolute = false; 128 asPath = true; 129 otherPath = false; 130 otherVals = { 131 attrset = false; 132 list = false; 133 int = false; 134 }; 135 }; 136 }; 137 138# LISTS 139 140 testFilter = { 141 expr = filter (x: x != "a") ["a" "b" "c" "a"]; 142 expected = ["b" "c"]; 143 }; 144 145 testFold = 146 let 147 f = op: fold: fold op 0 (range 0 100); 148 # fold with associative operator 149 assoc = f builtins.add; 150 # fold with non-associative operator 151 nonAssoc = f builtins.sub; 152 in { 153 expr = { 154 assocRight = assoc foldr; 155 # right fold with assoc operator is same as left fold 156 assocRightIsLeft = assoc foldr == assoc foldl; 157 nonAssocRight = nonAssoc foldr; 158 nonAssocLeft = nonAssoc foldl; 159 # with non-assoc operator the fold results are not the same 160 nonAssocRightIsNotLeft = nonAssoc foldl != nonAssoc foldr; 161 # fold is an alias for foldr 162 foldIsRight = nonAssoc fold == nonAssoc foldr; 163 }; 164 expected = { 165 assocRight = 5050; 166 assocRightIsLeft = true; 167 nonAssocRight = 50; 168 nonAssocLeft = (-5050); 169 nonAssocRightIsNotLeft = true; 170 foldIsRight = true; 171 }; 172 }; 173 174 testTake = testAllTrue [ 175 ([] == (take 0 [ 1 2 3 ])) 176 ([1] == (take 1 [ 1 2 3 ])) 177 ([ 1 2 ] == (take 2 [ 1 2 3 ])) 178 ([ 1 2 3 ] == (take 3 [ 1 2 3 ])) 179 ([ 1 2 3 ] == (take 4 [ 1 2 3 ])) 180 ]; 181 182 testFoldAttrs = { 183 expr = foldAttrs (n: a: [n] ++ a) [] [ 184 { a = 2; b = 7; } 185 { a = 3; c = 8; } 186 ]; 187 expected = { a = [ 2 3 ]; b = [7]; c = [8];}; 188 }; 189 190 testSort = { 191 expr = sort builtins.lessThan [ 40 2 30 42 ]; 192 expected = [2 30 40 42]; 193 }; 194 195 testToIntShouldConvertStringToInt = { 196 expr = toInt "27"; 197 expected = 27; 198 }; 199 200 testToIntShouldThrowErrorIfItCouldNotConvertToInt = { 201 expr = builtins.tryEval (toInt "\"foo\""); 202 expected = { success = false; value = false; }; 203 }; 204 205 testHasAttrByPathTrue = { 206 expr = hasAttrByPath ["a" "b"] { a = { b = "yey"; }; }; 207 expected = true; 208 }; 209 210 testHasAttrByPathFalse = { 211 expr = hasAttrByPath ["a" "b"] { a = { c = "yey"; }; }; 212 expected = false; 213 }; 214 215 216# ATTRSETS 217 218 # code from the example 219 testRecursiveUpdateUntil = { 220 expr = recursiveUpdateUntil (path: l: r: path == ["foo"]) { 221 # first attribute set 222 foo.bar = 1; 223 foo.baz = 2; 224 bar = 3; 225 } { 226 #second attribute set 227 foo.bar = 1; 228 foo.quz = 2; 229 baz = 4; 230 }; 231 expected = { 232 foo.bar = 1; # 'foo.*' from the second set 233 foo.quz = 2; # 234 bar = 3; # 'bar' from the first set 235 baz = 4; # 'baz' from the second set 236 }; 237 }; 238 239 240# GENERATORS 241# these tests assume attributes are converted to lists 242# in alphabetical order 243 244 testMkKeyValueDefault = { 245 expr = generators.mkKeyValueDefault {} ":" "f:oo" "bar"; 246 expected = ''f\:oo:bar''; 247 }; 248 249 testMkValueString = { 250 expr = let 251 vals = { 252 int = 42; 253 string = ''fo"o''; 254 bool = true; 255 bool2 = false; 256 null = null; 257 # float = 42.23; # floats are strange 258 }; 259 in mapAttrs 260 (const (generators.mkValueStringDefault {})) 261 vals; 262 expected = { 263 int = "42"; 264 string = ''fo"o''; 265 bool = "true"; 266 bool2 = "false"; 267 null = "null"; 268 # float = "42.23" true false [ "bar" ] ]''; 269 }; 270 }; 271 272 testToKeyValue = { 273 expr = generators.toKeyValue {} { 274 key = "value"; 275 "other=key" = "baz"; 276 }; 277 expected = '' 278 key=value 279 other\=key=baz 280 ''; 281 }; 282 283 testToINIEmpty = { 284 expr = generators.toINI {} {}; 285 expected = ""; 286 }; 287 288 testToINIEmptySection = { 289 expr = generators.toINI {} { foo = {}; bar = {}; }; 290 expected = '' 291 [bar] 292 293 [foo] 294 ''; 295 }; 296 297 testToINIDefaultEscapes = { 298 expr = generators.toINI {} { 299 "no [ and ] allowed unescaped" = { 300 "and also no = in keys" = 42; 301 }; 302 }; 303 expected = '' 304 [no \[ and \] allowed unescaped] 305 and also no \= in keys=42 306 ''; 307 }; 308 309 testToINIDefaultFull = { 310 expr = generators.toINI {} { 311 "section 1" = { 312 attribute1 = 5; 313 x = "Me-se JarJar Binx"; 314 # booleans are converted verbatim by default 315 boolean = false; 316 }; 317 "foo[]" = { 318 "he\\h=he" = "this is okay"; 319 }; 320 }; 321 expected = '' 322 [foo\[\]] 323 he\h\=he=this is okay 324 325 [section 1] 326 attribute1=5 327 boolean=false 328 x=Me-se JarJar Binx 329 ''; 330 }; 331 332 /* right now only invocation check */ 333 testToJSONSimple = 334 let val = { 335 foobar = [ "baz" 1 2 3 ]; 336 }; 337 in { 338 expr = generators.toJSON {} val; 339 # trivial implementation 340 expected = builtins.toJSON val; 341 }; 342 343 /* right now only invocation check */ 344 testToYAMLSimple = 345 let val = { 346 list = [ { one = 1; } { two = 2; } ]; 347 all = 42; 348 }; 349 in { 350 expr = generators.toYAML {} val; 351 # trivial implementation 352 expected = builtins.toJSON val; 353 }; 354 355 testToPretty = { 356 expr = mapAttrs (const (generators.toPretty {})) rec { 357 int = 42; 358 bool = true; 359 string = ''fno"rd''; 360 path = /. + "/foo"; # toPath returns a string 361 null_ = null; 362 function = x: x; 363 functionArgs = { arg ? 4, foo }: arg; 364 list = [ 3 4 function [ false ] ]; 365 attrs = { foo = null; "foo bar" = "baz"; }; 366 drv = derivation { name = "test"; system = builtins.currentSystem; }; 367 }; 368 expected = rec { 369 int = "42"; 370 bool = "true"; 371 string = ''"fno\"rd"''; 372 path = "/foo"; 373 null_ = "null"; 374 function = "<λ>"; 375 functionArgs = "<λ:{(arg),foo}>"; 376 list = "[ 3 4 ${function} [ false ] ]"; 377 attrs = "{ \"foo\" = null; \"foo bar\" = \"baz\"; }"; 378 drv = "<δ:test>"; 379 }; 380 }; 381 382 testToPrettyAllowPrettyValues = { 383 expr = generators.toPretty { allowPrettyValues = true; } 384 { __pretty = v: "«" + v + "»"; val = "foo"; }; 385 expected = "«foo»"; 386 }; 387 388 389# MISC 390 391 testOverridableDelayableArgsTest = { 392 expr = 393 let res1 = defaultOverridableDelayableArgs id {}; 394 res2 = defaultOverridableDelayableArgs id { a = 7; }; 395 res3 = let x = defaultOverridableDelayableArgs id { a = 7; }; 396 in (x.merge) { b = 10; }; 397 res4 = let x = defaultOverridableDelayableArgs id { a = 7; }; 398 in (x.merge) ( x: { b = 10; }); 399 res5 = let x = defaultOverridableDelayableArgs id { a = 7; }; 400 in (x.merge) ( x: { a = builtins.add x.a 3; }); 401 res6 = let x = defaultOverridableDelayableArgs id { a = 7; mergeAttrBy = { a = builtins.add; }; }; 402 y = x.merge {}; 403 in (y.merge) { a = 10; }; 404 405 resRem7 = res6.replace (a: removeAttrs a ["a"]); 406 407 # fixed tests (delayed args): (when using them add some comments, please) 408 resFixed1 = 409 let x = defaultOverridableDelayableArgs id ( x: { a = 7; c = x.fixed.b; }); 410 y = x.merge (x: { name = "name-${builtins.toString x.fixed.c}"; }); 411 in (y.merge) { b = 10; }; 412 strip = attrs: removeAttrs attrs ["merge" "replace"]; 413 in all id 414 [ ((strip res1) == { }) 415 ((strip res2) == { a = 7; }) 416 ((strip res3) == { a = 7; b = 10; }) 417 ((strip res4) == { a = 7; b = 10; }) 418 ((strip res5) == { a = 10; }) 419 ((strip res6) == { a = 17; }) 420 ((strip resRem7) == {}) 421 ((strip resFixed1) == { a = 7; b = 10; c =10; name = "name-10"; }) 422 ]; 423 expected = true; 424 }; 425 426}