2
0
Fork 0

WiP! build tests with nixos-module system

This commit is contained in:
Ehmry - 2020-10-23 00:04:58 +02:00
parent 5db9421732
commit c765ba3b02
7 changed files with 285 additions and 36 deletions

View File

@ -139,15 +139,12 @@
checks =
# Checks for continous testing
let tests = import ./tests;
in
with (forAllCrossSystems ({ system, localSystem, crossSystem }:
import ./tests {
inherit self;
apps = self.apps.${system};
localPackages = nixpkgsFor.${localSystem};
genodepkgs = self.packages.${system};
lib = self.lib.${system};
nixpkgs = nixpkgsFor.${system};
legacyPackages = self.legacyPackages.${system};
tests {
flake = self;
inherit system localSystem crossSystem;
} // {
ports = nixpkgsFor.${localSystem}.symlinkJoin {
name = "ports";

View File

@ -0,0 +1,93 @@
# genodeInit.children is an attrset of nixos configurations, like containers
{ config, pkgs, lib, ... }:
with lib;
{
imports = [ ];
options.genode.init = {
config = mkOption {
description = "Dhall configuration of this init instance";
type = types.either types.str types.path;
};
inputs = mkOption {
description = "List of packages to build a ROM store with.";
type = types.listOf types.package;
};
subinits = mkOption {
type = types.attrsOf (types.submodule ({ config, options, name, ... }: {
options = {
config = mkOption {
description = ''
A specification of the desired configuration of this sub-init, as a NixOS module.
'';
type =
let confPkgs = if config.pkgs == null then pkgs else config.pkgs;
in lib.mkOptionType {
name = "Toplevel NixOS config";
merge = loc: defs:
(import (confPkgs.path + "/nixos/lib/eval-config.nix") {
inherit system;
pkgs = confPkgs;
baseModules =
import (confPkgs.path + "/nixos/modules/module-list.nix");
inherit (confPkgs) lib;
modules = let
extraConfig = {
_file = "module at ${__curPos.file}:${
toString __curPos.line
}";
config = { };
};
in [ extraConfig ] ++ (map (x: x.value) defs);
prefix = [ "containers" name ];
}).config;
};
};
pkgs = mkOption {
type = types.nullOr types.attrs;
default = null;
example = literalExample "pkgs";
description = ''
Customise which nixpkgs to use for this container.
'';
};
};
config = mkMerge [
(mkIf options.config.isDefined {
path = config.config.system.build.toplevel;
})
];
}));
default = { };
};
};
config = {
system.build.initXml = pkgs.buildPackages.runCommand "init.xml" {
nativeBuildInputs = with pkgs.buildPackages; [ dhall xorg.lndir ];
DHALL_GENODE = "${pkgs.genodePackages.dhallGenode}/binary.dhall";
INIT_CONFIG = config.genode.init.config;
} ''
export XDG_CACHE_HOME=$NIX_BUILD_TOP
lndir -silent \
${pkgs.genodePackages.dhallGenode}/.cache \
$XDG_CACHE_HOME
dhall text <<< "(env:DHALL_GENODE).Init.render (env:INIT_CONFIG)" > $out
'';
};
}

View File

@ -1,21 +1,31 @@
{ self, apps, localPackages, genodepkgs, lib, nixpkgs, legacyPackages }:
{ flake, system, localSystem, crossSystem }:
let
apps = flake.apps.${system};
localPackages = flake.legacyPackages.${localSystem};
genodepkgs = flake.packages.${system};
lib = flake.lib.${system};
nixpkgs = flake.legacyPackages.${system};
legacyPackages = flake.legacyPackages.${system};
in with import ./lib/build-vms.nix {
inherit flake system localSystem crossSystem;
pkgs = flake.legacyPackages.${system};
localPackages = flake.inputs.nixpkgs.legacyPackages.${localSystem};
modulesPath = "${flake.inputs.nixpkgs}/nixos/modules";
};
with flake.legacyPackages.${system};
let
callTest = path:
import path {
pkgs = testPkgs;
inherit nixpkgs localPackages legacyPackages;
};
testFiles = map callTest [
testSpecs = map (p: import p) [
./log.nix
./posix.nix
./tox-bootstrapd.nix
./vmm_arm.nix
./vmm_x86.nix
./x86.nix
] ++ (callTest ./solo5);
# ./posix.nix
# ./tox-bootstrapd.nix
# ./vmm_arm.nix
# ./vmm_x86.nix
# ./x86.nix
]; # TODO ++ (callTest ./solo5);
testPkgs = genodepkgs;
@ -27,6 +37,7 @@ let
x86_64-genode = "${qemuPkg}/bin/qemu-system-x86_64";
}.${genodepkgs.stdenv.hostPlatform.system};
# TODO: move the cores into nixos modules
cores = [
{
prefix = "hw-pc-";
@ -141,6 +152,7 @@ let
let
testDriverName = "genode-test-driver-${name}";
# TODO: move buildVM into a nixos module
buildVM = vmName:
{ config, inputs, env ? { }, extraPaths ? [ ] }:
let
@ -178,7 +190,6 @@ let
./test-wrapper.dhall
} (${config}) $(stat --format '%s' ${storeTarball}/store.tar) ${storeManifest} ${manifest}";
env' = {
DHALL_GENODE = "${testPkgs.dhallGenode}/source.dhall";
DHALL_GENODE_TEST = "${./test.dhall}";
} // env;
@ -197,7 +208,10 @@ let
''${apps.render-init.program} <<< "(${config'}).config" > $out'';
};
nodes = lib.mapAttrs buildVM
# nodes = lib.mapAttrs buildVM
# (t.nodes or (if t ? machine then { machine = t.machine; } else { }));
nodes = buildVirtualNetwork
(t.nodes or (if t ? machine then { machine = t.machine; } else { }));
testScript' =
@ -207,7 +221,9 @@ let
else
testScript;
vms = map (node: node.script) (lib.attrValues nodes);
vlans = map (m: m.config.virtualisation.vlans) (lib.attrValues nodes);
vms = map (m: m.config.system.build.vm) (lib.attrValues nodes);
# Generate onvenience wrappers for running the test driver
# interactively with the specified network, and for starting the
@ -285,7 +301,7 @@ let
} else
null;
in lib.lists.crossLists f [ cores' testFiles ];
in lib.lists.crossLists f [ cores' testSpecs ];
in builtins.listToAttrs (builtins.filter (_: _ != null) testList)

109
tests/lib/build-vms.nix Normal file
View File

@ -0,0 +1,109 @@
{ flake, system, localSystem, crossSystem
# Nixpkgs, for qemu, lib and more
, localPackages, pkgs, modulesPath }:
with pkgs.lib;
with import ./qemu-flags.nix { inherit pkgs; };
rec {
inherit pkgs;
qemu = pkgs.qemu_test;
# Build a virtual network from an attribute set `{ machine1 =
# config1; ... machineN = configN; }', where `machineX' is the
# hostname and `configX' is a NixOS system configuration. Each
# machine is given an arbitrary IP address in the virtual network.
buildVirtualNetwork = nodes:
let nodesOut = mapAttrs (n: buildVM nodesOut) (assignIPAddresses nodes);
in nodesOut;
buildVM = nodes: configurations:
import "${modulesPath}/../lib/eval-config.nix" {
inherit system;
modules = configurations;
baseModules = (import "${modulesPath}/module-list.nix") ++ [
"${modulesPath}/virtualisation/qemu-vm.nix"
"${modulesPath}/testing/test-instrumentation.nix" # !!! should only get added for automated test runs
{
key = "no-manual";
documentation.nixos.enable = false;
}
{
key = "qemu";
system.build.qemu = qemu;
}
{
key = "nodes";
_module.args.nodes = nodes;
}
{
nixpkgs = {
inherit system crossSystem localSystem;
pkgs = flake.legacyPackages.${system};
};
}
];
};
# Given an attribute set { machine1 = config1; ... machineN =
# configN; }, sequentially assign IP addresses in the 192.168.1.0/24
# range to each machine, and set the hostname to the attribute name.
assignIPAddresses = nodes:
let
machines = attrNames nodes;
machinesNumbered = zipLists machines (range 1 254);
nodes_ = forEach machinesNumbered (m:
nameValuePair m.fst [
({ config, nodes, ... }:
let
interfacesNumbered =
zipLists config.virtualisation.vlans (range 1 255);
interfaces = forEach interfacesNumbered ({ fst, snd }:
nameValuePair "eth${toString snd}" {
ipv4.addresses = [{
address = "192.168.${toString fst}.${toString m.snd}";
prefixLength = 24;
}];
});
in {
key = "ip-address";
config = {
networking.hostName = mkDefault m.fst;
networking.interfaces = listToAttrs interfaces;
networking.primaryIPAddress = optionalString (interfaces != [ ])
(head (head interfaces).value.ipv4.addresses).address;
# Put the IP addresses of all VMs in this machine's
# /etc/hosts file. If a machine has multiple
# interfaces, use the IP address corresponding to
# the first interface (i.e. the first network in its
# virtualisation.vlans option).
networking.extraHosts = flip concatMapStrings machines (m':
let config = (getAttr m' nodes).config;
in optionalString (config.networking.primaryIPAddress != "")
("${config.networking.primaryIPAddress} "
+ optionalString (config.networking.domain != null)
"${config.networking.hostName}.${config.networking.domain} "
+ ''
${config.networking.hostName}
''));
virtualisation.qemu.options = forEach interfacesNumbered
({ fst, snd }: qemuNICFlags snd fst m.snd);
};
})
(getAttr m.fst nodes)
]);
in listToAttrs nodes_;
}

32
tests/lib/qemu-flags.nix Normal file
View File

@ -0,0 +1,32 @@
# QEMU flags shared between various Nix expressions.
{ pkgs }:
let
zeroPad = n:
pkgs.lib.optionalString (n < 16) "0" +
(if n > 255
then throw "Can't have more than 255 nets or nodes!"
else pkgs.lib.toHexString n);
in
rec {
qemuNicMac = net: machine: "52:54:00:12:${zeroPad net}:${zeroPad machine}";
qemuNICFlags = nic: net: machine:
[ "-device virtio-net-pci,netdev=vlan${toString nic},mac=${qemuNicMac net machine}"
"-netdev vde,id=vlan${toString nic},sock=$QEMU_VDE_SOCKET_${toString net}"
];
qemuSerialDevice = if pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64 then "ttyS0"
else if pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64 then "ttyAMA0"
else throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'";
qemuBinary = qemuPkg: {
x86_64-linux = "${qemuPkg}/bin/qemu-kvm -cpu max";
armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -enable-kvm -machine virt -cpu host";
aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -enable-kvm -machine virt,gic-version=host -cpu host";
x86_64-darwin = "${qemuPkg}/bin/qemu-kvm -cpu max";
aarch64-genode = "${qemuPkg}/bin/qemu-system-aarch64 -M virt,virtualization=true,gic_version=3 -cpu cortex-a53";
x86_64-genode = "${qemuPkg}/bin/qemu-system-x86_64 -machine q35";
}.${pkgs.stdenv.hostPlatform.system} or "${qemuPkg}/bin/qemu-kvm";
}

View File

@ -1,10 +1,10 @@
let Test = ./test.dhall ? env:DHALL_GENODE_TEST
let Genode = Test.Genode
let Genode =
env:DHALL_GENODE
? https://git.sr.ht/~ehmry/dhall-genode/blob/master/package.dhall
let Child = Genode.Init.Child
in Test::{
in Genode.Init::{
, children = toMap
{ test-log =
Child.flat

View File

@ -1,11 +1,13 @@
{ pkgs, ... }:
with pkgs;
{
name = "log";
machine = {
config = ./log.dhall;
inputs = [ (pkgs.genodeSources.depot "test-log") ];
machine = { config, pkgs, ... }: {
imports = [
../nixos-modules/genode-init.nix
];
genode.init = {
config = ./log.dhall;
inputs = [ (pkgs.genodeSources.depot "test-log") ];
};
};
testScript = ''
start_all()