nixpkgs/lib/tests/checkAndMergeCompat.nix
NAHO 6177c4ad72
lib: remove optional builtins prefixes from prelude functions
Remove optional builtins prefixes from prelude functions by running:

    builtins=(
      abort
      baseNameOf
      break
      derivation
      derivationStrict
      dirOf
      false
      fetchGit
      fetchMercurial
      fetchTarball
      fetchTree
      fromTOML
      import
      isNull
      map
      null
      placeholder
      removeAttrs
      scopedImport
      throw
      toString
      true
    )

    fd --type file . lib --exec-batch sed --in-place --regexp-extended "
      s/\<builtins\.($(
        printf '%s\n' "${builtins[@]}" |
          paste --delimiter '|' --serial -
      ))\>/\1/g
    "

    nix fmt
2025-09-30 09:02:59 +02:00

380 lines
9.2 KiB
Nix

{
pkgs ? import ../.. { },
currLibPath ? ../.,
prevLibPath ? "${
pkgs.fetchFromGitHub {
owner = "nixos";
repo = "nixpkgs";
# Parent commit of [#391544](https://github.com/NixOS/nixpkgs/pull/391544)
# Which was before the type.merge.v2 introduction
rev = "bcf94dd3f07189b7475d823c8d67d08b58289905";
hash = "sha256-MuMiIY3MX5pFSOCvutmmRhV6RD0R3CG0Hmazkg8cMFI=";
}
}/lib",
}:
let
lib = import currLibPath;
lib_with_merge_v2 = lib;
lib_with_merge_v1 = import prevLibPath;
getMatrix =
{
getType ? null,
# If getType is set this is only used as test prefix
# And the type from getType is used
outerTypeName,
innerTypeName,
value,
testAttrs,
}:
let
evalModules.call_v1 = lib_with_merge_v1.evalModules;
evalModules.call_v2 = lib_with_merge_v2.evalModules;
outerTypes.outer_v1 = lib_with_merge_v1.types;
outerTypes.outer_v2 = lib_with_merge_v2.types;
innerTypes.inner_v1 = lib_with_merge_v1.types;
innerTypes.inner_v2 = lib_with_merge_v2.types;
in
lib.mapAttrs (
_: evalModules:
lib.mapAttrs (
_: outerTypes:
lib.mapAttrs (_: innerTypes: {
"test_${outerTypeName}_${innerTypeName}" = testAttrs // {
expr =
(evalModules {
modules = [
(m: {
options.foo = m.lib.mkOption {
type =
if getType != null then
getType outerTypes innerTypes
else
outerTypes.${outerTypeName} innerTypes.${innerTypeName};
default = value;
};
})
];
}).config.foo;
};
}) innerTypes
) outerTypes
) evalModules;
in
{
# AttrsOf string
attrsOf_str_ok = getMatrix {
outerTypeName = "attrsOf";
innerTypeName = "str";
value = {
bar = "test";
};
testAttrs = {
expected = {
bar = "test";
};
};
};
attrsOf_str_err_inner = getMatrix {
outerTypeName = "attrsOf";
innerTypeName = "str";
value = {
bar = 1; # not a string
};
testAttrs = {
expectedError = {
type = "ThrownError";
msg = "A definition for option `foo.bar' is not of type `string'.*";
};
};
};
attrsOf_str_err_outer = getMatrix {
outerTypeName = "attrsOf";
innerTypeName = "str";
value = [ "foo" ]; # not an attrset
testAttrs = {
expectedError = {
type = "ThrownError";
msg = "A definition for option `foo' is not of type `attribute set of string'.*";
};
};
};
# listOf string
listOf_str_ok = getMatrix {
outerTypeName = "listOf";
innerTypeName = "str";
value = [
"foo"
"bar"
];
testAttrs = {
expected = [
"foo"
"bar"
];
};
};
listOf_str_err_inner = getMatrix {
outerTypeName = "listOf";
innerTypeName = "str";
value = [
"foo"
1
]; # not a string
testAttrs = {
expectedError = {
type = "ThrownError";
msg = ''A definition for option `foo."\[definition 1-entry 2\]"' is not of type `string'.'';
};
};
};
listOf_str_err_outer = getMatrix {
outerTypeName = "listOf";
innerTypeName = "str";
value = {
foo = 42;
}; # not a list
testAttrs = {
expectedError = {
type = "ThrownError";
msg = "A definition for option `foo' is not of type `list of string'.*";
};
};
};
attrsOf_submodule_ok = getMatrix {
getType =
a: b:
a.attrsOf (
b.submodule (m: {
options.nested = m.lib.mkOption {
type = m.lib.types.str;
};
})
);
outerTypeName = "attrsOf";
innerTypeName = "submodule";
value = {
foo = {
nested = "test1";
};
bar = {
nested = "test2";
};
};
testAttrs = {
expected = {
foo = {
nested = "test1";
};
bar = {
nested = "test2";
};
};
};
};
attrsOf_submodule_err_inner = getMatrix {
outerTypeName = "attrsOf";
innerTypeName = "submodule";
getType =
a: b:
a.attrsOf (
b.submodule (m: {
options.nested = m.lib.mkOption {
type = m.lib.types.str;
};
})
);
value = {
foo = [ 1 ]; # not a submodule
bar = {
nested = "test2";
};
};
testAttrs = {
expectedError = {
type = "ThrownError";
msg = "A definition for option `foo.foo' is not of type `submodule'.*";
};
};
};
attrsOf_submodule_err_outer = getMatrix {
outerTypeName = "attrsOf";
innerTypeName = "submodule";
getType =
a: b:
a.attrsOf (
b.submodule (m: {
options.nested = m.lib.mkOption {
type = m.lib.types.str;
};
})
);
value = [ 123 ]; # not an attrsOf
testAttrs = {
expectedError = {
type = "ThrownError";
msg = ''A definition for option `foo' is not of type `attribute set of \(submodule\).*'';
};
};
};
# either
either_str_attrsOf_ok = getMatrix {
outerTypeName = "either";
innerTypeName = "str_or_attrsOf_str";
getType = a: b: a.either b.str (b.attrsOf a.str);
value = "string value";
testAttrs = {
expected = "string value";
};
};
either_str_attrsOf_err_1 = getMatrix {
outerTypeName = "either";
innerTypeName = "str_or_attrsOf_str";
getType = a: b: a.either b.str (b.attrsOf a.str);
value = 1;
testAttrs = {
expectedError = {
type = "ThrownError";
msg = "A definition for option `foo' is not of type `string or attribute set of string'.*";
};
};
};
either_str_attrsOf_err_2 = getMatrix {
outerTypeName = "either";
innerTypeName = "str_or_attrsOf_str";
getType = a: b: a.either b.str (b.attrsOf a.str);
value = {
bar = 1; # not a string
};
testAttrs = {
expectedError = {
type = "ThrownError";
msg = "A definition for option `foo.bar' is not of type `string'.*";
};
};
};
# Coereced to
coerce_attrsOf_str_to_listOf_str_run = getMatrix {
outerTypeName = "coercedTo";
innerTypeName = "attrsOf_str->listOf_str";
getType = a: b: a.coercedTo (b.attrsOf b.str) builtins.attrValues (b.listOf b.str);
value = {
bar = "test1"; # coerced to listOf string
foo = "test2"; # coerced to listOf string
};
testAttrs = {
expected = [
"test1"
"test2"
];
};
};
coerce_attrsOf_str_to_listOf_str_final = getMatrix {
outerTypeName = "coercedTo";
innerTypeName = "attrsOf_str->listOf_str";
getType = a: b: a.coercedTo (b.attrsOf b.str) (abort "This shouldnt run") (b.listOf b.str);
value = [
"test1"
"test2"
]; # already a listOf string
testAttrs = {
expected = [
"test1"
"test2"
]; # Order should be kept
};
};
coerce_attrsOf_str_to_listOf_err_coercer_input = getMatrix {
outerTypeName = "coercedTo";
innerTypeName = "attrsOf_str->listOf_str";
getType = a: b: a.coercedTo (b.attrsOf b.str) builtins.attrValues (b.listOf b.str);
value = [
{ }
{ }
]; # not coercible to listOf string, with the given coercer
testAttrs = {
expectedError = {
type = "ThrownError";
msg = ''A definition for option `foo."\[definition 1-entry 1\]"' is not of type `string'.*'';
};
};
};
coerce_attrsOf_str_to_listOf_err_coercer_ouput = getMatrix {
outerTypeName = "coercedTo";
innerTypeName = "attrsOf_str->listOf_str";
getType = a: b: a.coercedTo (b.attrsOf b.str) builtins.attrValues (b.listOf b.str);
value = {
foo = {
bar = 1;
}; # coercer produces wrong type -> [ { bar = 1; } ]
};
testAttrs = {
expectedError = {
type = "ThrownError";
msg = ''A definition for option `foo."\[definition 1-entry 1\]"' is not of type `string'.*'';
};
};
};
coerce_str_to_int_coercer_ouput = getMatrix {
outerTypeName = "coercedTo";
innerTypeName = "int->str";
getType = a: b: a.coercedTo b.int toString a.str;
value = [ ];
testAttrs = {
expectedError = {
type = "ThrownError";
msg = ''A definition for option `foo' is not of type `string or signed integer convertible to it.*'';
};
};
};
# Submodule
submodule_with_ok = getMatrix {
outerTypeName = "submoduleWith";
innerTypeName = "mixed_types";
getType =
a: b:
a.submodule (m: {
options.attrs = m.lib.mkOption {
type = b.attrsOf b.str;
};
options.list = m.lib.mkOption {
type = b.listOf b.str;
};
options.either = m.lib.mkOption {
type = b.either a.str a.int;
};
});
value = {
attrs = {
foo = "bar";
};
list = [
"foo"
"bar"
];
either = 123; # int
};
testAttrs = {
expected = {
attrs = {
foo = "bar";
};
list = [
"foo"
"bar"
];
either = 123;
};
};
};
}