diff --git a/lib/default.nix b/lib/default.nix index 0c0e2d5e10217..58fe09182e15d 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -71,7 +71,7 @@ let importJSON importTOML warn warnIf warnIfNot throwIf throwIfNot checkListOfEnum info showWarnings nixpkgsVersion version isInOldestRelease mod compare splitByAndCompare - functionArgs setFunctionArgs isFunction toFunction + functionArgs setFunctionArgs isFunction toFunction lazyFunction toHexString toBaseDigits inPureEvalMode; inherit (self.fixedPoints) fix fix' converge extends composeExtensions composeManyExtensions makeExtensible makeExtensibleWithCustomName; diff --git a/lib/systems/default.nix b/lib/systems/default.nix index 233174d40831c..439f8ac6d617a 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -204,7 +204,7 @@ rec { emulator = pkgs: if (final.emulatorAvailable pkgs) then selectEmulator pkgs - else throw "Don't know how to run ${final.config} executables."; + else throw "Don't know how to run ${final.config} executables on ${pkgs.stdenv.hostPlatform.system}."; }) // mapAttrs (n: v: v final.parsed) inspect.predicates // mapAttrs (n: v: v final.gcc.arch or "default") architectures.predicates diff --git a/lib/trivial.nix b/lib/trivial.nix index 5d4fad8266bc9..eff5db60c6f01 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -1,5 +1,9 @@ { lib }: +let + inherit (lib) mapAttrs functionArgs setFunctionArgs; +in + rec { ## Simple (higher order) functions @@ -467,6 +471,29 @@ rec { then v else k: v; + /* + Make an attribute-set matching function such as `{ a, b }: b` delay + its evaluation of the attribute set in the argument. + + This is not compatible with ellipsis patterns, `{ ... }:`. It removes the + ability to do `args@{ a, ... }: args.b`, although this limitation should + not be relied on. + + Example: + + lib.fix (lib.lazyFunction ({ a, b }: { a = b; b = 1; })) + */ + lazyFunction = f: + setFunctionArgs + (args: + f + (mapAttrs + (k: _: args.${k}) + (functionArgs f) + ) + ) + (functionArgs f) ; + /* Convert the given positive integer to a string of its hexadecimal representation. For example: diff --git a/nixos/lib/testing-python.nix b/nixos/lib/testing-python.nix index f63b6c78f6da3..726b202e0027b 100644 --- a/nixos/lib/testing-python.nix +++ b/nixos/lib/testing-python.nix @@ -1,5 +1,6 @@ { system , pkgs ? import ../.. { inherit system config; } +, hostPkgs ? pkgs # Use a minimal kernel? , minimal ? false # Ignored @@ -25,7 +26,8 @@ rec { extraTestModule = { config = { - hostPkgs = pkgs; + _module.args.pkgs = pkgs; + inherit hostPkgs; }; }; diff --git a/nixos/lib/testing/nodes.nix b/nixos/lib/testing/nodes.nix index 765af2878dfe8..159306b982746 100644 --- a/nixos/lib/testing/nodes.nix +++ b/nixos/lib/testing/nodes.nix @@ -1,13 +1,10 @@ -testModuleArgs@{ config, lib, hostPkgs, nodes, ... }: +testModuleArgs@{ config, lib, hostPkgs, pkgs, nodes, ... }: let inherit (lib) mkOption mkForce optional types mapAttrs mkDefault mdDoc; - system = hostPkgs.stdenv.hostPlatform.system; - baseOS = import ../eval-config.nix { - inherit system; inherit (config.node) specialArgs; modules = [ config.defaults ]; baseModules = (import ../../modules/module-list.nix) ++ @@ -17,10 +14,14 @@ let ({ config, ... }: { virtualisation.qemu.package = testModuleArgs.config.qemu.package; + virtualisation.host.pkgs = hostPkgs; # Ensure we do not use aliases. Ideally this is only set # when the test framework is used by Nixpkgs NixOS tests. nixpkgs.config.allowAliases = false; + nixpkgs = { + inherit (pkgs.stdenv) hostPlatform buildPlatform; + }; }) testModuleArgs.config.extraBaseModules ] ++ optional config.minimal ../../modules/testing/minimal-kernel.nix; diff --git a/nixos/lib/testing/pkgs.nix b/nixos/lib/testing/pkgs.nix index 22dd586868e30..3f3e2b29038f3 100644 --- a/nixos/lib/testing/pkgs.nix +++ b/nixos/lib/testing/pkgs.nix @@ -2,7 +2,7 @@ { config = { # default pkgs for use in VMs - _module.args.pkgs = hostPkgs; + _module.args.pkgs = lib.mkDefault hostPkgs; defaults = { # TODO: a module to set a shared pkgs, if options.nixpkgs.* is untouched by user (highestPrio) */ diff --git a/nixos/lib/testing/run.nix b/nixos/lib/testing/run.nix index 0cd07d8afd21d..c0dd8c0735c4e 100644 --- a/nixos/lib/testing/run.nix +++ b/nixos/lib/testing/run.nix @@ -1,6 +1,13 @@ { config, hostPkgs, lib, ... }: let inherit (lib) types mkOption mdDoc; + + vmHostPlatform = hostPkgs.stdenv.buildPlatform; + + virtualisationFeature = + if vmHostPlatform.isLinux then [ "kvm" ] + else if vmHostPlatform.isDarwin then [ "hvf" ] + else throw "Don't know how to require virtualisation on platform ${vmHostPlatform.system}"; in { options = { @@ -33,7 +40,7 @@ in derivation = hostPkgs.stdenv.mkDerivation { name = "vm-test-run-${config.name}"; - requiredSystemFeatures = [ "kvm" "nixos-test" ]; + requiredSystemFeatures = virtualisationFeature ++ [ "nixos-test" ]; buildCommand = '' mkdir -p $out diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 8ec73cc05c86a..a2fdcee024856 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -1,5 +1,6 @@ { system, pkgs, + hostPkgs ? pkgs, # Projects the test configuration into a the desired value; usually # the test runner: `config: config.test`. @@ -28,10 +29,10 @@ let # in that file, which are then forwarded to the test definition # following the `import make-test-python.nix` expression # (if it is a function). - discoverTests (val { inherit system pkgs; }) + discoverTests (val { inherit system pkgs hostPkgs; }) else val; handleTest = path: args: - discoverTests (import path ({ inherit system pkgs; } // args)); + discoverTests (lazyFunction (import path) ({ inherit system pkgs hostPkgs; } // args)); handleTestOn = systems: path: args: if elem system systems then handleTest path args else {}; @@ -45,7 +46,7 @@ let inherit (rec { - doRunTest = arg: ((import ../lib/testing-python.nix { inherit system pkgs; }).evalTest { + doRunTest = arg: ((import ../lib/testing-python.nix { inherit system pkgs hostPkgs; }).evalTest { imports = [ arg ]; }).config.result; findTests = tree: diff --git a/nixos/tests/make-test-python.nix b/nixos/tests/make-test-python.nix index c3bbd67423726..e0787c34bbbce 100644 --- a/nixos/tests/make-test-python.nix +++ b/nixos/tests/make-test-python.nix @@ -1,10 +1,11 @@ f: { system ? builtins.currentSystem, pkgs ? import ../.. { inherit system; }, + hostPkgs ? pkgs, ... } @ args: -with import ../lib/testing-python.nix { inherit system pkgs; }; +with import ../lib/testing-python.nix { inherit system pkgs hostPkgs; }; let testConfig = makeTest (if pkgs.lib.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f); in testConfig.test # For nix-build diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 2d629a1966cc2..ce57b4f2dd1ff 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -139,16 +139,35 @@ with pkgs; ### Push NixOS tests inside the fixed point # See also allTestsForSystem in nixos/release.nix - nixosTests = import ../../nixos/tests/all-tests.nix { - inherit pkgs; - system = stdenv.hostPlatform.system; + nixosTests = let + systemArgs = + if stdenv.hostPlatform.isLinux && (stdenv.buildPlatform.isLinux || stdenv.buildPlatform.isDarwin) + then { + hostPkgs = pkgs.buildPackages; + pkgs = pkgs; + system = stdenv.hostPlatform.system; + } + else if stdenv.hostPlatform.isDarwin && stdenv.buildPlatform.isDarwin + then + # In the context of a normal darwin compile, repurpose nixosTests as a + # non-cross build. This requires a "remote" builder such as a local + # Linux VM, but all VM hosting happens on darwin. + let linuxSystem = "${stdenv.buildPlatform.parsed.cpu.name}-linux"; + in { + hostPkgs = pkgs; + pkgs = import ../.. { inherit config overlays; system = linuxSystem; }; + system = linuxSystem; + } + else throw "Don't know how to configure NixOS for VM host ${stdenv.buildPlatform.system} and/or VM guest ${stdenv.hostPlatform.system} built on ${stdenv.buildPlatform.system}"; + in + import ../../nixos/tests/all-tests.nix { + inherit (systemArgs) hostPkgs pkgs system; callTest = config: config.test; } // { # for typechecking of the scripts and evaluation of # the nodes, without running VMs. allDrivers = import ../../nixos/tests/all-tests.nix { - inherit pkgs; - system = stdenv.hostPlatform.system; + inherit (systemArgs) hostPkgs pkgs system; callTest = config: config.test.driver; }; };