kernel: fix config generation

Addresses https://github.com/NixOS/nixpkgs/issues/71803:
Kernel options are not merged as described, especially the "optional"
aspects. The error silences legitimate warnings.
This commit is contained in:
Matthieu Coudron 2020-04-01 03:20:33 +02:00
parent ae6bdcc535
commit b9a4e6953d
4 changed files with 64 additions and 40 deletions

View file

@ -8,10 +8,10 @@ with lib;
option = x:
x // { optional = true; };
yes = { tristate = "y"; };
no = { tristate = "n"; };
module = { tristate = "m"; };
freeform = x: { freeform = x; };
yes = { tristate = "y"; optional = false; };
no = { tristate = "n"; optional = false; };
module = { tristate = "m"; optional = false; };
freeform = x: { freeform = x; optional = false; };
/*
Common patterns/legacy used in common-config/hardened-config.nix

View file

@ -22,7 +22,7 @@ let
mergeFalseByDefault = locs: defs:
if defs == [] then abort "This case should never happen."
else if any (x: x == false) defs then false
else if any (x: x == false) (getValues defs) then false
else true;
kernelItem = types.submodule {
@ -55,6 +55,7 @@ let
default = false;
description = ''
Wether option should generate a failure when unused.
Upon merging values, mandatory wins over optional.
'';
};
};
@ -121,7 +122,7 @@ in
type = types.attrsOf kernelItem;
example = literalExample '' with lib.kernel; {
"9P_NET" = yes;
USB = optional yes;
USB = option yes;
MMC_BLOCK_MINORS = freeform "32";
}'';
description = ''

View file

@ -158,11 +158,8 @@ let
;
}).config;
#
structuredConfig = moduleStructuredConfig.settings;
};
}; # end of configfile derivation
kernel = (callPackage ./manual-config.nix {}) {

View file

@ -1,53 +1,79 @@
# to run these tests:
# nix-instantiate --eval --strict . -A tests.kernel-config
#
# make sure to use NON EXISTING kernel settings else they may conflict with
# common-config.nix
{ lib, pkgs }:
with lib.kernel;
with lib.asserts;
with lib.modules;
with lib;
with kernel;
# To test nixos/modules/system/boot/kernel_config.nix;
let
# copied from release-lib.nix
assertTrue = bool:
if bool
then pkgs.runCommand "evaluated-to-true" {} "touch $out"
else pkgs.runCommand "evaluated-to-false" {} "false";
lts_kernel = pkgs.linuxPackages.kernel;
kernelTestConfig = structuredConfig: (lts_kernel.override {
structuredExtraConfig = structuredConfig;
}).configfile.structuredConfig;
# to see the result once the module transformed the lose structured config
getConfig = structuredConfig:
(lts_kernel.override {
structuredExtraConfig = structuredConfig;
}).configfile.structuredConfig;
mandatoryVsOptionalConfig = mkMerge [
{ USB_DEBUG = option yes;}
{ USB_DEBUG = yes;}
{ NIXOS_FAKE_USB_DEBUG = yes;}
{ NIXOS_FAKE_USB_DEBUG = option yes; }
];
freeformConfig = mkMerge [
{ MMC_BLOCK_MINORS = freeform "32"; } # same as default, won't trigger any error
{ MMC_BLOCK_MINORS = freeform "64"; } # will trigger an error but the message is not great:
{ NIXOS_FAKE_MMC_BLOCK_MINORS = freeform "32"; } # same as default, won't trigger any error
{ NIXOS_FAKE_MMC_BLOCK_MINORS = freeform "64"; } # will trigger an error but the message is not great:
];
yesWinsOverNoConfig = mkMerge [
# default for "8139TOO_PIO" is no
{ "8139TOO_PIO" = yes; } # yes wins over no by default
{ "8139TOO_PIO" = no; }
# default for "NIXOS_TEST_BOOLEAN" is no
{ "NIXOS_TEST_BOOLEAN" = yes; } # yes wins over no by default
{ "NIXOS_TEST_BOOLEAN" = no; }
];
optionalNoWins = mkMerge [
{ NIXOS_FAKE_USB_DEBUG = option yes;}
{ NIXOS_FAKE_USB_DEBUG = yes;}
];
allOptionalRemainOptional = mkMerge [
{ NIXOS_FAKE_USB_DEBUG = option yes;}
{ NIXOS_FAKE_USB_DEBUG = option yes;}
];
in
{
runTests {
testEasy = {
expr = (getConfig { NIXOS_FAKE_USB_DEBUG = yes;}).NIXOS_FAKE_USB_DEBUG;
expected = { tristate = "y"; optional = false; freeform = null; };
};
# mandatory flag should win over optional
mandatoryCheck = (kernelTestConfig mandatoryVsOptionalConfig);
testMandatoryCheck = {
expr = (getConfig mandatoryVsOptionalConfig).NIXOS_FAKE_USB_DEBUG.optional;
expected = false;
};
testYesWinsOverNo = {
expr = (getConfig yesWinsOverNoConfig)."NIXOS_TEST_BOOLEAN".tristate;
expected = "y";
};
testAllOptionalRemainOptional = {
expr = (getConfig allOptionalRemainOptional)."NIXOS_FAKE_USB_DEBUG".optional;
expected = true;
};
# check that freeform options are unique
# Should trigger
# > The option `settings.MMC_BLOCK_MINORS.freeform' has conflicting definitions, in `<unknown-file>' and `<unknown-file>'
freeformCheck = let
res = builtins.tryEval ( (kernelTestConfig freeformConfig).MMC_BLOCK_MINORS.freeform);
in
assertTrue (res.success == false);
# > The option `settings.NIXOS_FAKE_MMC_BLOCK_MINORS.freeform' has conflicting definitions, in `<unknown-file>' and `<unknown-file>'
testTreeform = let
res = builtins.tryEval ( (getConfig freeformConfig).NIXOS_FAKE_MMC_BLOCK_MINORS.freeform);
in {
expr = res.success;
expected = false;
};
yesVsNoCheck = let
res = kernelTestConfig yesWinsOverNoConfig;
in
assertTrue (res."8139TOO_PIO".tristate == "y");
}