mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-11-10 17:54:53 +01:00
`check` can have a new place since the introduction of
merge.v2. This makes the // { check = ... } idiom unreliable.
In this PR we add checks to detect and report this.
merge.v2 introduced in:
https://github.com/NixOS/nixpkgs/pull/391544
Real world case:
https://hercules-ci.com/github/hercules-ci/hercules-ci-effects/jobs/875
118 lines
3.4 KiB
Nix
118 lines
3.4 KiB
Nix
# Tests for v2 merge check coherence
|
|
{ lib, ... }:
|
|
let
|
|
inherit (lib) types mkOption;
|
|
|
|
# The problematic pattern: overriding check with //
|
|
# This inner type should reject everything (check always returns false)
|
|
adhocOverrideType = (types.lazyAttrsOf types.raw) // {
|
|
check = _: false;
|
|
};
|
|
|
|
# Using addCheck is the correct way to add custom checks
|
|
properlyCheckedType = types.addCheck (types.lazyAttrsOf types.raw) (v: v ? foo);
|
|
|
|
# Using addCheck with a check that will fail
|
|
failingCheckedType = types.addCheck (types.lazyAttrsOf types.raw) (v: v ? foo);
|
|
|
|
# Ad-hoc override on outer type
|
|
adhocOuterType = types.lazyAttrsOf types.int // {
|
|
check = _: false;
|
|
};
|
|
|
|
# Ad-hoc override on left side of either
|
|
adhocEitherLeft = types.lazyAttrsOf types.raw // {
|
|
check = _: false;
|
|
};
|
|
|
|
# Ad-hoc override on coercedType in coercedTo
|
|
adhocCoercedFrom = types.lazyAttrsOf types.raw // {
|
|
check = _: false;
|
|
};
|
|
|
|
# Ad-hoc override on finalType in coercedTo
|
|
adhocCoercedTo = types.lazyAttrsOf types.raw // {
|
|
check = _: false;
|
|
};
|
|
|
|
# Ad-hoc override wrapped in addCheck
|
|
adhocAddCheck = types.addCheck (types.lazyAttrsOf types.raw // { check = _: false; }) (v: true);
|
|
in
|
|
{
|
|
# Test 1: Ad-hoc check override in nested type should be detected
|
|
options.adhocFail = mkOption {
|
|
type = types.lazyAttrsOf adhocOverrideType;
|
|
default = { };
|
|
};
|
|
config.adhocFail = {
|
|
foo = { };
|
|
};
|
|
|
|
# Test 1b: Ad-hoc check override in outer type should be detected
|
|
options.adhocOuterFail = mkOption {
|
|
type = adhocOuterType;
|
|
default = { };
|
|
};
|
|
config.adhocOuterFail.bar = 42;
|
|
|
|
# Test 1c: Ad-hoc check override on left side of either type
|
|
options.eitherLeftFail = mkOption {
|
|
type = types.either adhocEitherLeft types.int;
|
|
};
|
|
config.eitherLeftFail.foo = { };
|
|
|
|
# Test 1d: Ad-hoc check override on right side of either type
|
|
options.eitherRightFail = mkOption {
|
|
type = types.either types.int (types.lazyAttrsOf types.raw // { check = _: false; });
|
|
};
|
|
config.eitherRightFail.foo = { };
|
|
|
|
# Test 1e: Ad-hoc check override on coercedType in coercedTo
|
|
options.coercedFromFail = mkOption {
|
|
type = types.coercedTo adhocCoercedFrom (x: { bar = 1; }) (types.lazyAttrsOf types.int);
|
|
};
|
|
config.coercedFromFail = {
|
|
foo = { };
|
|
};
|
|
|
|
# Test 1f: Ad-hoc check override on finalType in coercedTo
|
|
options.coercedToFail = mkOption {
|
|
type = types.coercedTo types.str (x: { }) adhocCoercedTo;
|
|
};
|
|
config.coercedToFail.foo = { };
|
|
|
|
# Test 1g: Ad-hoc check override wrapped in addCheck
|
|
options.addCheckNested = mkOption {
|
|
type = adhocAddCheck;
|
|
};
|
|
config.addCheckNested.foo = { };
|
|
|
|
# Test 2: Using addCheck should work correctly
|
|
options.addCheckPass = mkOption {
|
|
type = types.lazyAttrsOf properlyCheckedType;
|
|
default = { };
|
|
};
|
|
config.addCheckPass.bar.foo = "value";
|
|
|
|
# Test 3: addCheck should validate values properly
|
|
options.addCheckFail = mkOption {
|
|
type = types.lazyAttrsOf failingCheckedType;
|
|
default = { };
|
|
};
|
|
config.addCheckFail.bar.baz = "value"; # Missing required 'foo' attribute
|
|
|
|
# Test 4: Normal v2 types should work without coherence errors
|
|
options.normalPass = mkOption {
|
|
type = types.lazyAttrsOf (types.attrsOf types.int);
|
|
default = { };
|
|
};
|
|
config.normalPass.foo.bar = 42;
|
|
|
|
# Success assertion - only checks things that should succeed
|
|
options.result = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
};
|
|
config.result = true;
|
|
}
|