fake.modules transposition for aspect-oriented Dendritic Nix. with cross-aspect dependencies. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix aspect oriented

Split tests (#19)

* split tests, reorg types

authored by oeiuwq.com and committed by

GitHub 72ffc008 83c8e441

+622 -518
+58 -509
checkmate/modules/tests.nix
··· 1 - { inputs, ... }: 2 - { 3 - perSystem = 4 - { lib, ... }: 5 - let 6 - transpose = import ../../nix { inherit lib; }; 1 + { inputs, lib, ... }: 2 + let 3 + targetNix = "${inputs.target}/nix"; 4 + targetLib = "${inputs.target}/nix/lib.nix"; 5 + targetMod = "${inputs.target}/nix/flakeModule.nix"; 7 6 8 - mkFlake = 9 - mod: 10 - inputs.flake-parts.lib.mkFlake 11 - { 12 - inputs.self = [ ]; 13 - } 14 - { 15 - systems = [ ]; 16 - imports = [ 17 - ../../nix/flakeModule.nix 18 - inputs.flake-parts.flakeModules.modules 19 - mod 20 - (fooMod "aspectOne") 21 - (fooMod "aspectTwo") 22 - (fooMod "aspectThree") 23 - ]; 24 - }; 7 + transpose = import targetNix { inherit lib; }; 25 8 26 - fooMod = aspect: { 9 + mkFlake = 10 + mod: 11 + inputs.flake-parts.lib.mkFlake 12 + { 13 + inputs.self = [ ]; 14 + } 15 + { 16 + systems = [ ]; 27 17 imports = [ 28 - { flake.modules.classOne.${aspect}.imports = [ fooOpt ]; } 29 - { flake.modules.classTwo.${aspect}.imports = [ fooOpt ]; } 30 - { flake.modules.classThree.${aspect}.imports = [ fooOpt ]; } 18 + targetMod 19 + inputs.flake-parts.flakeModules.modules 20 + mod 21 + (fooMod "aspectOne") 22 + (fooMod "aspectTwo") 23 + (fooMod "aspectThree") 31 24 ]; 32 25 }; 33 26 34 - fooOpt = { 35 - options.foo = lib.mkOption { 36 - type = lib.types.str; 37 - default = "<unset>"; 38 - }; 39 - options.bar = lib.mkOption { 40 - type = lib.types.listOf lib.types.str; 41 - default = [ ]; 42 - }; 43 - options.baz = lib.mkOption { 44 - type = lib.types.lazyAttrsOf lib.types.str; 45 - default = { }; 46 - }; 47 - }; 48 - 49 - evalMod = 50 - class: mod: 51 - (lib.evalModules { 52 - inherit class; 53 - modules = [ mod ]; 54 - }).config; 55 - in 56 - { 57 - nix-unit.tests = { 58 - transpose."test swaps parent and child attrNames" = { 59 - expr = transpose { a.b.c = 1; }; 60 - expected = { 61 - b.a.c = 1; 62 - }; 63 - }; 64 - 65 - transpose."test common childs become one parent" = { 66 - expr = transpose { 67 - a.b = 1; 68 - c.b = 2; 69 - }; 70 - expected.b = { 71 - a = 1; 72 - c = 2; 73 - }; 74 - }; 75 - 76 - new-scope."test usage without flakes" = 77 - let 78 - flake-aspects-lib = import ../../nix/lib.nix lib; 79 - # first eval is like evaling the flake. 80 - first = lib.evalModules { 81 - modules = [ 82 - (flake-aspects-lib.new-scope "hello") 83 - { 84 - hello.aspects = 85 - { aspects, ... }: 86 - { 87 - a.b.c = [ "world" ]; 88 - a.includes = [ aspects.x ]; 89 - x.b = 90 - { lib, ... }: 91 - { 92 - c = lib.splitString " " "mundo cruel"; 93 - }; 94 - }; 95 - } 96 - ]; 97 - }; 98 - # second eval is like evaling its nixosConfiguration 99 - second = lib.evalModules { 100 - modules = [ 101 - { options.c = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 102 - first.config.hello.modules.b.a 103 - ]; 104 - }; 105 - expr = lib.sort (a: b: a < b) second.config.c; 106 - expected = [ 107 - "cruel" 108 - "mundo" 109 - "world" 110 - ]; 111 - in 112 - { 113 - inherit expr expected; 114 - }; 115 - 116 - aspects."test provides default" = 117 - let 118 - flake = 119 - inputs.flake-parts.lib.mkFlake 120 - { 121 - inputs.self = [ ]; 122 - moduleLocation = builtins.toString ./.; 123 - } 124 - { 125 - systems = [ ]; 126 - imports = [ 127 - ../../nix/flakeModule.nix 128 - inputs.flake-parts.flakeModules.modules 129 - ]; 130 - }; 131 - expr = flake.modules; 132 - expected = { }; 133 - in 134 - { 135 - inherit expr expected; 136 - }; 137 - 138 - aspects."test transposes to flake.modules" = 139 - let 140 - flake = mkFlake { 141 - flake.aspects.aspectOne = { 142 - classOne.foo = "niri"; 143 - classTwo.foo = "paper.spoon"; 144 - }; 145 - }; 146 - expr = { 147 - classOne = (evalMod "classOne" flake.modules.classOne.aspectOne).foo; 148 - classTwo = (evalMod "classTwo" flake.modules.classTwo.aspectOne).foo; 149 - }; 150 - expected = { 151 - classOne = "niri"; 152 - classTwo = "paper.spoon"; 153 - }; 154 - in 155 - { 156 - inherit expr expected; 157 - }; 158 - 159 - aspects."test dependencies on aspects" = 160 - let 161 - flake = mkFlake { 162 - flake.aspects = 163 - { aspects, ... }: 164 - { 165 - aspectOne = { 166 - description = "os config"; 167 - includes = with aspects; [ aspectTwo ]; 168 - classOne.bar = [ "os" ]; 169 - }; 170 - 171 - aspectTwo = { 172 - description = "user config at os level"; 173 - classOne.bar = [ "user" ]; 174 - }; 175 - }; 176 - }; 177 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 178 - expected = [ 179 - "os" 180 - "user" 181 - ]; 182 - in 183 - { 184 - inherit expr expected; 185 - }; 186 - 187 - aspects."test resolve aspect-chain" = 188 - let 189 - flake = mkFlake { 190 - flake.aspects = 191 - { aspects, ... }: 192 - { 193 - aspectOne = { 194 - name = "one"; 195 - includes = [ aspects.aspectOne.provides.dos ]; 196 - classOne.bar = [ "zzz" ]; 197 - provides.dos = 198 - { aspect-chain, ... }: 199 - { 200 - name = "dos"; 201 - includes = [ aspects.aspectOne.provides.tres ]; 202 - classOne.bar = map (x: x.name) aspect-chain; 203 - }; 27 + fooMod = aspect: { 28 + imports = [ 29 + { flake.modules.classOne.${aspect}.imports = [ fooOpt ]; } 30 + { flake.modules.classTwo.${aspect}.imports = [ fooOpt ]; } 31 + { flake.modules.classThree.${aspect}.imports = [ fooOpt ]; } 32 + ]; 33 + }; 204 34 205 - provides.tres = 206 - { aspect-chain, ... }: 207 - { 208 - name = "tres"; 209 - classOne.bar = [ (lib.last aspect-chain).name ]; 210 - }; 211 - }; 212 - }; 213 - }; 214 - mod = { 215 - imports = [ 216 - fooOpt 217 - (flake.aspects.aspectOne.resolve { class = "classOne"; }) 218 - ]; 219 - }; 220 - expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 221 - expected = [ 222 - "dos" 223 - "one" 224 - "zzz" 225 - ]; 226 - in 227 - { 228 - inherit expr expected; 229 - }; 35 + fooOpt = { 36 + options.foo = lib.mkOption { 37 + type = lib.types.str; 38 + default = "<unset>"; 39 + }; 40 + options.bar = lib.mkOption { 41 + type = lib.types.listOf lib.types.str; 42 + default = [ ]; 43 + }; 44 + options.baz = lib.mkOption { 45 + type = lib.types.lazyAttrsOf lib.types.str; 46 + default = { }; 47 + }; 48 + }; 230 49 231 - aspects."test modules resolved" = 232 - let 233 - flake = mkFlake { 234 - flake.aspects = 235 - { aspects, ... }: 236 - { 237 - aspectOne = { 238 - name = "one"; 239 - includes = [ aspects.aspectOne.provides.dos ]; 240 - classOne.bar = [ "zzz" ]; 241 - provides.dos = 242 - { aspect-chain, ... }: 243 - { 244 - name = "dos"; 245 - includes = [ aspects.aspectOne.provides.tres ]; 246 - classOne.bar = map (x: x.name) aspect-chain; 247 - }; 248 - 249 - provides.tres = 250 - { aspect-chain, ... }: 251 - { 252 - name = "tres"; 253 - classOne.bar = [ (lib.last aspect-chain).name ]; 254 - }; 255 - }; 256 - }; 257 - }; 258 - mod = { 259 - imports = [ 260 - fooOpt 261 - (flake.aspects.aspectOne.modules.classOne) 262 - ]; 263 - }; 264 - expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 265 - expected = [ 266 - "dos" 267 - "one" 268 - "zzz" 269 - ]; 270 - in 271 - { 272 - inherit expr expected; 273 - }; 274 - 275 - aspects."test provides" = 276 - let 277 - flake = mkFlake { 278 - flake.aspects = 279 - { aspects, ... }: 280 - { 281 - aspectOne.includes = with aspects.aspectTwo.provides; [ 282 - foo 283 - bar 284 - ]; 285 - aspectOne.classOne = { }; # must be present for mixing dependencies. 286 - aspectTwo = { 287 - classOne.bar = [ "class one not included" ]; 288 - classTwo.bar = [ "class two not included" ]; 289 - provides.foo = 290 - { class, aspect-chain }: 291 - { 292 - name = "aspectTwo.foo"; 293 - description = "aspectTwo foo provided"; 294 - includes = [ 295 - aspects.aspectThree.provides.moo 296 - aspects.aspectTwo.provides.baz 297 - ]; 298 - classOne.bar = [ "two:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 299 - classTwo.bar = [ "foo class two not included" ]; 300 - }; 301 - # a provider can be immediately an aspect object. 302 - provides.bar = { 303 - # classOne is missing on bar 304 - classTwo.bar = [ "bar class two not included" ]; 305 - }; 306 - # _ is an shortcut alias of provides. 307 - _.baz = { 308 - # classOne is missing on bar 309 - classTwo.bar = [ "baz" ]; 310 - }; 311 - }; 312 - aspectThree.provides.moo = 313 - { aspect-chain, class }: 314 - { 315 - classOne.bar = [ "three:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 316 - }; 317 - }; 318 - }; 319 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 320 - expected = [ 321 - "three:classOne:aspectOne/aspectTwo.foo" 322 - "two:classOne:aspectOne" 323 - ]; 324 - in 325 - { 326 - inherit expr expected; 327 - }; 328 - 329 - aspects."test provides using fixpoints" = 330 - let 331 - flake = mkFlake { 332 - flake.aspects = 333 - { aspects, ... }: 334 - { 335 - aspectOne = { 336 - classOne.bar = [ "1" ]; 337 - includes = [ 338 - aspects.aspectTwo 339 - ]; 340 - }; 341 - 342 - aspectTwo = { 343 - classOne.bar = [ "2" ]; 344 - includes = [ aspects.aspectTwo.provides.three-and-four-and-five ]; 345 - provides = 346 - { provides, ... }: 347 - { 348 - three-and-four-and-five = { 349 - classOne.bar = [ "3" ]; 350 - includes = [ 351 - provides.four 352 - aspects.five 353 - ]; 354 - }; 355 - four = { 356 - classOne.bar = [ "4" ]; 357 - }; 358 - }; 359 - }; 360 - 361 - five.classOne.bar = [ "5" ]; 362 - }; 363 - }; 364 - 365 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 366 - expected = [ 367 - "1" 368 - "2" 369 - "3" 370 - "4" 371 - "5" 372 - ]; 373 - in 374 - { 375 - inherit expr expected; 376 - }; 377 - 378 - aspects."test provides parametrized modules" = 379 - let 380 - flake = mkFlake { 381 - flake.aspects = 382 - { aspects, ... }: 383 - { 384 - aspectOne.includes = [ (aspects.aspectTwo.provides.hello "mundo") ]; 385 - aspectOne.classOne.bar = [ "1" ]; 386 - 387 - aspectTwo.provides.hello = world: { 388 - classOne.bar = [ world ]; 389 - }; 390 - }; 391 - }; 392 - 393 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 394 - expected = [ 395 - "1" 396 - "mundo" 397 - ]; 398 - in 399 - { 400 - inherit expr expected; 401 - }; 402 - 403 - aspects."test override default provider" = 404 - let 405 - flake = mkFlake { 406 - flake.aspects = 407 - { aspects, ... }: 408 - { 409 - aspectOne = 410 - { aspect, ... }: 411 - { 412 - includes = [ (aspects.aspectTwo { message = "hello ${aspect.name}"; }) ]; 413 - classOne = { }; # required for propagation 414 - }; 415 - 416 - aspectTwo.__functor = 417 - _: 418 - { message }: # args must be always named 419 - { class, aspect-chain }: 420 - { aspect, ... }: 421 - { 422 - classOne.bar = [ 423 - "foo" 424 - aspect.name 425 - message 426 - class 427 - ] 428 - ++ (lib.map (x: x.name) aspect-chain); 429 - }; 430 - aspectTwo.classOne.bar = [ "itself not included" ]; 431 - }; 432 - }; 433 - 434 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 435 - expected = [ 436 - "foo" 437 - "<function body>" 438 - "hello aspectOne" 439 - "classOne" 440 - "aspectOne" 441 - ]; 442 - in 443 - { 444 - inherit expr expected; 445 - }; 446 - 447 - aspects."test override default provider includes" = 448 - let 449 - flake = mkFlake { 450 - flake.aspects = 451 - { aspects, ... }: 452 - { 453 - aspectOne = { 454 - classOne.bar = [ "should-not-be-present" ]; 455 - includes = [ aspects.aspectTwo ]; 456 - __functor = aspect: { 457 - includes = [ 458 - { classOne.bar = [ "from-functor" ]; } 459 - ] 460 - ++ map (f: f { message = "hello"; }) aspect.includes; 461 - }; 462 - }; 463 - aspectTwo.__functor = 464 - _aspect: 465 - { message }: 466 - { 467 - classOne.bar = [ message ]; 468 - }; 469 - }; 470 - }; 471 - 472 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 473 - expected = [ 474 - "hello" 475 - "from-functor" 476 - ]; 477 - in 478 - { 479 - inherit expr expected; 480 - }; 481 - 482 - aspects."test define top-level context-aware aspect" = 483 - let 484 - flake = mkFlake { 485 - flake.aspects = 486 - { aspects, ... }: 487 - { 488 - aspectOne = { 489 - classOne.bar = [ "should-not-be-present" ]; 490 - includes = [ aspects.aspectTwo ]; 491 - __functor = aspect: { 492 - includes = [ 493 - { classOne.bar = [ "from-functor" ]; } 494 - ] 495 - ++ map (f: f { message = "hello"; }) aspect.includes; 496 - }; 497 - }; 498 - aspectTwo = 499 - { message }: 500 - { 501 - classOne.bar = [ message ]; 502 - }; 503 - }; 504 - }; 505 - 506 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 507 - expected = [ 508 - "hello" 509 - "from-functor" 510 - ]; 511 - in 512 - { 513 - inherit expr expected; 514 - }; 515 - }; 516 - 517 - }; 50 + evalMod = 51 + class: mod: 52 + (lib.evalModules { 53 + inherit class; 54 + modules = [ mod ]; 55 + }).config; 56 + in 57 + { 58 + _module.args = { 59 + inherit 60 + transpose 61 + targetLib 62 + targetMod 63 + targetNix 64 + ; 65 + inherit mkFlake evalMod fooOpt; 66 + }; 518 67 }
+53
checkmate/modules/tests/aspect_chain.nix
··· 1 + { 2 + lib, 3 + mkFlake, 4 + evalMod, 5 + fooOpt, 6 + ... 7 + }: 8 + { 9 + 10 + flake.tests."test resolve aspect-chain" = 11 + let 12 + flake = mkFlake { 13 + flake.aspects = 14 + { aspects, ... }: 15 + { 16 + aspectOne = { 17 + name = "one"; 18 + includes = [ aspects.aspectOne.provides.dos ]; 19 + classOne.bar = [ "zzz" ]; 20 + provides.dos = 21 + { aspect-chain, ... }: 22 + { 23 + name = "dos"; 24 + includes = [ aspects.aspectOne.provides.tres ]; 25 + classOne.bar = map (x: x.name) aspect-chain; 26 + }; 27 + 28 + provides.tres = 29 + { aspect-chain, ... }: 30 + { 31 + name = "tres"; 32 + classOne.bar = [ (lib.last aspect-chain).name ]; 33 + }; 34 + }; 35 + }; 36 + }; 37 + mod = { 38 + imports = [ 39 + fooOpt 40 + (flake.aspects.aspectOne.resolve { class = "classOne"; }) 41 + ]; 42 + }; 43 + expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 44 + expected = [ 45 + "dos" 46 + "one" 47 + "zzz" 48 + ]; 49 + in 50 + { 51 + inherit expr expected; 52 + }; 53 + }
+53
checkmate/modules/tests/aspect_default_provider_functor.nix
··· 1 + { 2 + mkFlake, 3 + evalMod, 4 + lib, 5 + ... 6 + }: 7 + { 8 + 9 + flake.tests."test override default provider" = 10 + let 11 + flake = mkFlake { 12 + flake.aspects = 13 + { aspects, ... }: 14 + { 15 + aspectOne = 16 + { aspect, ... }: 17 + { 18 + includes = [ (aspects.aspectTwo { message = "hello ${aspect.name}"; }) ]; 19 + classOne = { }; # required for propagation 20 + }; 21 + 22 + aspectTwo.__functor = 23 + _: 24 + { message }: # args must be always named 25 + { class, aspect-chain }: 26 + { aspect, ... }: 27 + { 28 + classOne.bar = [ 29 + "foo" 30 + aspect.name 31 + message 32 + class 33 + ] 34 + ++ (lib.map (x: x.name) aspect-chain); 35 + }; 36 + aspectTwo.classOne.bar = [ "itself not included" ]; 37 + }; 38 + }; 39 + 40 + expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 41 + expected = [ 42 + "foo" 43 + "<function body>" 44 + "hello aspectOne" 45 + "classOne" 46 + "aspectOne" 47 + ]; 48 + in 49 + { 50 + inherit expr expected; 51 + }; 52 + 53 + }
+42
checkmate/modules/tests/aspect_default_provider_override.nix
··· 1 + { 2 + mkFlake, 3 + evalMod, 4 + ... 5 + }: 6 + { 7 + 8 + flake.tests."test override default provider includes" = 9 + let 10 + flake = mkFlake { 11 + flake.aspects = 12 + { aspects, ... }: 13 + { 14 + aspectOne = { 15 + classOne.bar = [ "should-not-be-present" ]; 16 + includes = [ aspects.aspectTwo ]; 17 + __functor = aspect: { 18 + includes = [ 19 + { classOne.bar = [ "from-functor" ]; } 20 + ] 21 + ++ map (f: f { message = "hello"; }) aspect.includes; 22 + }; 23 + }; 24 + aspectTwo.__functor = 25 + _aspect: 26 + { message }: 27 + { 28 + classOne.bar = [ message ]; 29 + }; 30 + }; 31 + }; 32 + 33 + expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 34 + expected = [ 35 + "hello" 36 + "from-functor" 37 + ]; 38 + in 39 + { 40 + inherit expr expected; 41 + }; 42 + }
+37
checkmate/modules/tests/aspect_dependencies.nix
··· 1 + { 2 + mkFlake, 3 + evalMod, 4 + lib, 5 + ... 6 + }: 7 + { 8 + 9 + flake.tests."test dependencies on aspects" = 10 + let 11 + flake = mkFlake { 12 + flake.aspects = 13 + { aspects, ... }: 14 + { 15 + aspectOne = { 16 + description = "os config"; 17 + includes = with aspects; [ aspectTwo ]; 18 + classOne.bar = [ "os" ]; 19 + }; 20 + 21 + aspectTwo = { 22 + description = "user config at os level"; 23 + classOne.bar = [ "user" ]; 24 + }; 25 + }; 26 + }; 27 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 28 + expected = [ 29 + "os" 30 + "user" 31 + ]; 32 + in 33 + { 34 + inherit expr expected; 35 + }; 36 + 37 + }
+58
checkmate/modules/tests/aspect_fixpoint.nix
··· 1 + { 2 + lib, 3 + mkFlake, 4 + evalMod, 5 + ... 6 + }: 7 + { 8 + 9 + flake.tests."test provides using fixpoints" = 10 + let 11 + flake = mkFlake { 12 + flake.aspects = 13 + { aspects, ... }@top: 14 + { 15 + aspectOne = { 16 + classOne.bar = [ "1" ]; 17 + includes = [ 18 + aspects.aspectTwo 19 + ]; 20 + }; 21 + 22 + aspectTwo = { 23 + classOne.bar = [ "2" ]; 24 + includes = [ aspects.aspectTwo.provides.three-and-four-and-five ]; 25 + provides = 26 + { aspects, ... }: 27 + { 28 + three-and-four-and-five = { 29 + classOne.bar = [ "3" ]; 30 + includes = [ 31 + aspects.four 32 + top.aspects.five 33 + ]; 34 + }; 35 + four = { 36 + classOne.bar = [ "4" ]; 37 + }; 38 + }; 39 + }; 40 + 41 + five.classOne.bar = [ "5" ]; 42 + }; 43 + }; 44 + 45 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 46 + expected = [ 47 + "1" 48 + "2" 49 + "3" 50 + "4" 51 + "5" 52 + ]; 53 + in 54 + { 55 + inherit expr expected; 56 + }; 57 + 58 + }
+54
checkmate/modules/tests/aspect_modules_resolved.nix
··· 1 + { 2 + lib, 3 + mkFlake, 4 + evalMod, 5 + fooOpt, 6 + ... 7 + }: 8 + { 9 + 10 + flake.tests."test modules resolved" = 11 + let 12 + flake = mkFlake { 13 + flake.aspects = 14 + { aspects, ... }: 15 + { 16 + aspectOne = { 17 + name = "one"; 18 + includes = [ aspects.aspectOne.provides.dos ]; 19 + classOne.bar = [ "zzz" ]; 20 + provides.dos = 21 + { aspect-chain, ... }: 22 + { 23 + name = "dos"; 24 + includes = [ aspects.aspectOne.provides.tres ]; 25 + classOne.bar = map (x: x.name) aspect-chain; 26 + }; 27 + 28 + provides.tres = 29 + { aspect-chain, ... }: 30 + { 31 + name = "tres"; 32 + classOne.bar = [ (lib.last aspect-chain).name ]; 33 + }; 34 + }; 35 + }; 36 + }; 37 + mod = { 38 + imports = [ 39 + fooOpt 40 + (flake.aspects.aspectOne.modules.classOne) 41 + ]; 42 + }; 43 + expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 44 + expected = [ 45 + "dos" 46 + "one" 47 + "zzz" 48 + ]; 49 + in 50 + { 51 + inherit expr expected; 52 + }; 53 + 54 + }
+34
checkmate/modules/tests/aspect_parametric.nix
··· 1 + { 2 + mkFlake, 3 + evalMod, 4 + lib, 5 + ... 6 + }: 7 + { 8 + 9 + flake.tests."test provides parametrized modules" = 10 + let 11 + flake = mkFlake { 12 + flake.aspects = 13 + { aspects, ... }: 14 + { 15 + aspectOne.includes = [ (aspects.aspectTwo.provides.hello "mundo") ]; 16 + aspectOne.classOne.bar = [ "1" ]; 17 + 18 + aspectTwo.provides.hello = world: { 19 + classOne.bar = [ world ]; 20 + }; 21 + }; 22 + }; 23 + 24 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 25 + expected = [ 26 + "1" 27 + "mundo" 28 + ]; 29 + in 30 + { 31 + inherit expr expected; 32 + }; 33 + 34 + }
+63
checkmate/modules/tests/aspect_provides.nix
··· 1 + { 2 + lib, 3 + mkFlake, 4 + evalMod, 5 + ... 6 + }: 7 + { 8 + 9 + flake.tests."test provides" = 10 + let 11 + flake = mkFlake { 12 + flake.aspects = 13 + { aspects, ... }: 14 + { 15 + aspectOne.includes = with aspects.aspectTwo.provides; [ 16 + foo 17 + bar 18 + ]; 19 + aspectOne.classOne = { }; # must be present for mixing dependencies. 20 + aspectTwo = { 21 + classOne.bar = [ "class one not included" ]; 22 + classTwo.bar = [ "class two not included" ]; 23 + provides.foo = 24 + { class, aspect-chain }: 25 + { 26 + name = "aspectTwo.foo"; 27 + description = "aspectTwo foo provided"; 28 + includes = [ 29 + aspects.aspectThree.provides.moo 30 + aspects.aspectTwo.provides.baz 31 + ]; 32 + classOne.bar = [ "two:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 33 + classTwo.bar = [ "foo class two not included" ]; 34 + }; 35 + # a provider can be immediately an aspect object. 36 + provides.bar = { 37 + # classOne is missing on bar 38 + classTwo.bar = [ "bar class two not included" ]; 39 + }; 40 + # _ is an shortcut alias of provides. 41 + _.baz = { 42 + # classOne is missing on bar 43 + classTwo.bar = [ "baz" ]; 44 + }; 45 + }; 46 + aspectThree.provides.moo = 47 + { aspect-chain, class }: 48 + { 49 + classOne.bar = [ "three:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 50 + }; 51 + }; 52 + }; 53 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 54 + expected = [ 55 + "three:classOne:aspectOne/aspectTwo.foo" 56 + "two:classOne:aspectOne" 57 + ]; 58 + in 59 + { 60 + inherit expr expected; 61 + }; 62 + 63 + }
+41
checkmate/modules/tests/aspect_toplevel_parametric.nix
··· 1 + { 2 + mkFlake, 3 + evalMod, 4 + ... 5 + }: 6 + { 7 + 8 + flake.tests."test define top-level context-aware aspect" = 9 + let 10 + flake = mkFlake { 11 + flake.aspects = 12 + { aspects, ... }: 13 + { 14 + aspectOne = { 15 + classOne.bar = [ "should-not-be-present" ]; 16 + includes = [ aspects.aspectTwo ]; 17 + __functor = aspect: { 18 + includes = [ 19 + { classOne.bar = [ "from-functor" ]; } 20 + ] 21 + ++ map (f: f { message = "hello"; }) aspect.includes; 22 + }; 23 + }; 24 + aspectTwo = 25 + { message }: 26 + { 27 + classOne.bar = [ message ]; 28 + }; 29 + }; 30 + }; 31 + 32 + expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 33 + expected = [ 34 + "hello" 35 + "from-functor" 36 + ]; 37 + in 38 + { 39 + inherit expr expected; 40 + }; 41 + }
+29
checkmate/modules/tests/default_empty.nix
··· 1 + { 2 + inputs, 3 + targetMod, 4 + ... 5 + }: 6 + { 7 + 8 + flake.tests."test provides default" = 9 + let 10 + flake = 11 + inputs.flake-parts.lib.mkFlake 12 + { 13 + inputs.self = [ ]; 14 + moduleLocation = builtins.toString ./.; 15 + } 16 + { 17 + systems = [ ]; 18 + imports = [ 19 + targetMod 20 + inputs.flake-parts.flakeModules.modules 21 + ]; 22 + }; 23 + expr = flake.modules; 24 + expected = { }; 25 + in 26 + { 27 + inherit expr expected; 28 + }; 29 + }
+28
checkmate/modules/tests/tranpose_flake_modules.nix
··· 1 + { 2 + mkFlake, 3 + evalMod, 4 + ... 5 + }: 6 + { 7 + 8 + flake.tests."test transposes to flake.modules" = 9 + let 10 + flake = mkFlake { 11 + flake.aspects.aspectOne = { 12 + classOne.foo = "niri"; 13 + classTwo.foo = "paper.spoon"; 14 + }; 15 + }; 16 + expr = { 17 + classOne = (evalMod "classOne" flake.modules.classOne.aspectOne).foo; 18 + classTwo = (evalMod "classTwo" flake.modules.classTwo.aspectOne).foo; 19 + }; 20 + expected = { 21 + classOne = "niri"; 22 + classTwo = "paper.spoon"; 23 + }; 24 + in 25 + { 26 + inherit expr expected; 27 + }; 28 + }
+15
checkmate/modules/tests/transpose_common.nix
··· 1 + { transpose, ... }: 2 + { 3 + 4 + flake.tests."test transpose common childs become one parent" = { 5 + expr = transpose { 6 + a.b = 1; 7 + c.b = 2; 8 + }; 9 + expected.b = { 10 + a = 1; 11 + c = 2; 12 + }; 13 + }; 14 + 15 + }
+10
checkmate/modules/tests/transpose_swap.nix
··· 1 + { transpose, ... }: 2 + { 3 + 4 + flake.tests."test transpose swaps parent and child attrNames" = { 5 + expr = transpose { a.b.c = 1; }; 6 + expected = { 7 + b.a.c = 1; 8 + }; 9 + }; 10 + }
+44
checkmate/modules/tests/without_flakes.nix
··· 1 + { lib, targetLib, ... }: 2 + { 3 + 4 + flake.tests."test usage without flakes" = 5 + let 6 + flake-aspects-lib = import targetLib lib; 7 + # first eval is like evaling the flake. 8 + first = lib.evalModules { 9 + modules = [ 10 + (flake-aspects-lib.new-scope "hello") 11 + { 12 + hello.aspects = 13 + { aspects, ... }: 14 + { 15 + a.b.c = [ "world" ]; 16 + a.includes = [ aspects.x ]; 17 + x.b = 18 + { lib, ... }: 19 + { 20 + c = lib.splitString " " "mundo cruel"; 21 + }; 22 + }; 23 + } 24 + ]; 25 + }; 26 + # second eval is like evaling its nixosConfiguration 27 + second = lib.evalModules { 28 + modules = [ 29 + { options.c = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 30 + first.config.hello.modules.b.a 31 + ]; 32 + }; 33 + expr = lib.sort (a: b: a < b) second.config.c; 34 + expected = [ 35 + "cruel" 36 + "mundo" 37 + "world" 38 + ]; 39 + in 40 + { 41 + inherit expr expected; 42 + }; 43 + 44 + }
+3 -9
nix/types.nix
··· 5 5 aspectsType = lib.types.submodule ( 6 6 { config, ... }: 7 7 { 8 - freeformType = lib.types.attrsOf (lib.types.either aspectSubmoduleAttrs providerType); 8 + freeformType = lib.types.attrsOf providerType; 9 9 config._module.args.aspects = config; 10 10 } 11 11 ); ··· 30 30 ); 31 31 32 32 functionProviderType = lib.types.either functionToAspect (lib.types.functionTo providerType); 33 - providerType = lib.types.either functionProviderType aspectSubmodule; 33 + providerType = lib.types.either aspectSubmoduleAttrs functionProviderType; 34 34 35 35 aspectSubmoduleAttrs = lib.types.addCheck aspectSubmodule ( 36 36 m: (!builtins.isFunction m) || (isAspectSubmoduleFn m) ··· 78 78 options.provides = lib.mkOption { 79 79 description = "Providers of aspect for other aspects"; 80 80 default = { }; 81 - type = lib.types.submodule ( 82 - { config, ... }: 83 - { 84 - freeformType = lib.types.attrsOf providerType; 85 - config._module.args.provides = config; 86 - } 87 - ); 81 + type = aspectsType; 88 82 }; 89 83 options.__functor = lib.mkOption { 90 84 internal = true;