Replace test framework
Adopt the Python test driver from NixOS. Temporarily drop Sotest runs.ncurses
parent
0dc02f60e5
commit
40c1977779
@ -1,89 +1,299 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
let tests = call: { log = call ./log.nix { }; };
|
||||
|
||||
in { self, apps, buildPackages, genodepkgs, lib, nixpkgs, legacyPackages }:
|
||||
{ self, apps, buildPackages, genodepkgs, lib, nixpkgs, legacyPackages }:
|
||||
|
||||
let
|
||||
|
||||
callTest = path:
|
||||
import path {
|
||||
pkgs = testPkgs;
|
||||
inherit nixpkgs buildPackages legacyPackages;
|
||||
};
|
||||
|
||||
testFiles = map callTest [
|
||||
./log.nix
|
||||
./posix.nix
|
||||
./vmm_x86.nix
|
||||
./x86.nix
|
||||
] ++ (callTest ./solo5);
|
||||
|
||||
testPkgs = genodepkgs;
|
||||
|
||||
addManifest = drv:
|
||||
drv // {
|
||||
manifest = nixpkgs.runCommand "${drv.name}.dhall" { inherit drv; } ''
|
||||
set -eu
|
||||
echo -n '[' >> $out
|
||||
find $drv/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out
|
||||
${if builtins.elem "lib" drv.outputs then
|
||||
''
|
||||
find ${drv.lib}/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out''
|
||||
else
|
||||
""}
|
||||
echo -n ']' >> $out
|
||||
qemu' = buildPackages.qemu_test;
|
||||
|
||||
qemuBinary = qemuPkg:
|
||||
{
|
||||
aarch64-genode = "${qemuPkg}/bin/qemu-system-aarch64";
|
||||
x86_64-genode = "${qemuPkg}/bin/qemu-system-x86_64";
|
||||
}.${genodepkgs.stdenv.hostPlatform.system};
|
||||
|
||||
platforms = [
|
||||
{
|
||||
prefix = "hw-pc-";
|
||||
specs = [ "x86" "hw" ];
|
||||
basePkg = testPkgs.base-hw-pc;
|
||||
makeImage = lib.hwImage;
|
||||
startVM = vmName: image: ''
|
||||
#! ${buildPackages.runtimeShell}
|
||||
exec ${qemuBinary qemu'} \
|
||||
-name ${vmName} \
|
||||
-machine q35 \
|
||||
-m 384 \
|
||||
-kernel "${testPkgs.bender}/bender" \
|
||||
-initrd "${image}/image.elf" \
|
||||
$QEMU_OPTS \
|
||||
"$@"
|
||||
'';
|
||||
}
|
||||
{
|
||||
prefix = "nova-";
|
||||
specs = [ "x86" "nova" ];
|
||||
basePkg = testPkgs.base-nova;
|
||||
makeImage = lib.novaImage;
|
||||
startVM = vmName: image: ''
|
||||
#! ${buildPackages.runtimeShell}
|
||||
exec ${qemuBinary qemu'} \
|
||||
-name ${vmName} \
|
||||
-machine q35 \
|
||||
-m 384 \
|
||||
-kernel "${testPkgs.bender}/bender" \
|
||||
-initrd "${testPkgs.NOVA}/hypervisor-x86_64 arg=iommu novpid serial,${image}/image.elf" \
|
||||
$QEMU_OPTS \
|
||||
"$@"
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
testDriver = with buildPackages;
|
||||
let testDriverScript = ./test-driver/test-driver.py;
|
||||
in stdenv.mkDerivation {
|
||||
name = "nixos-test-driver";
|
||||
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
buildInputs = [ (python3.withPackages (p: [ p.ptpython ])) ];
|
||||
checkInputs = with python3Packages; [ pylint mypy ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
preferLocalBuild = true;
|
||||
|
||||
doCheck = true;
|
||||
checkPhase = ''
|
||||
mypy --disallow-untyped-defs \
|
||||
--no-implicit-optional \
|
||||
--ignore-missing-imports ${testDriverScript}
|
||||
pylint --errors-only ${testDriverScript}
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
cp ${testDriverScript} $out/bin/nixos-test-driver
|
||||
chmod u+x $out/bin/nixos-test-driver
|
||||
# TODO: copy user script part into this file (append)
|
||||
|
||||
wrapProgram $out/bin/nixos-test-driver \
|
||||
--prefix PATH : "${lib.makeBinPath [ qemu' coreutils ]}" \
|
||||
'';
|
||||
};
|
||||
|
||||
nova = (call:
|
||||
((tests call) // {
|
||||
driver_manager = call ./driver_manager.nix { };
|
||||
posix = call ./posix.nix { };
|
||||
vmm = call ./vmm_x86.nix { };
|
||||
x86 = call ./x86.nix { };
|
||||
} // call ./solo5 { })) (import ./driver-nova.nix {
|
||||
inherit apps addManifest buildPackages lib nixpkgs testPkgs
|
||||
legacyPackages;
|
||||
}).callTest;
|
||||
|
||||
hw = (call:
|
||||
((tests call) // {
|
||||
posix = call ./posix.nix { };
|
||||
x86 = call ./x86.nix { };
|
||||
} // call ./solo5 { })) (import ./driver-hw.nix {
|
||||
inherit apps addManifest buildPackages lib nixpkgs testPkgs
|
||||
legacyPackages;
|
||||
}).callTest;
|
||||
|
||||
testsToList = tests:
|
||||
map (test: {
|
||||
inherit (test) name;
|
||||
value = test;
|
||||
}) (builtins.attrValues tests);
|
||||
|
||||
in with builtins;
|
||||
listToAttrs ((concatLists (map (testsToList) [ hw nova ]))) // {
|
||||
sotest = let
|
||||
hwTests = with hw; [ multi posix x86 ];
|
||||
novaTests = with nova; [ multi posix x86 vmm ];
|
||||
allTests = hwTests ++ novaTests;
|
||||
|
||||
projectCfg.boot_items =
|
||||
|
||||
(map (test: {
|
||||
inherit (test) name;
|
||||
exec = "bender";
|
||||
load = [ test.image.name ];
|
||||
}) hwTests)
|
||||
|
||||
++ (map (test: {
|
||||
inherit (test) name;
|
||||
exec = "bender";
|
||||
load = [ "hypervisor serial novga iommu" test.image.name ];
|
||||
}) novaTests);
|
||||
|
||||
in buildPackages.stdenv.mkDerivation {
|
||||
name = "sotest";
|
||||
buildCommand = ''
|
||||
mkdir zip; cd zip
|
||||
cp "${testPkgs.bender}/bender" bender
|
||||
cp "${testPkgs.NOVA}/hypervisor-x86_64" hypervisor
|
||||
${concatStringsSep "\n"
|
||||
(map (test: "cp ${test.image}/image.elf ${test.image.name}") allTests)}
|
||||
mkdir -p $out/nix-support
|
||||
${buildPackages.zip}/bin/zip "$out/binaries.zip" *
|
||||
cat << EOF > "$out/project.json"
|
||||
${builtins.toJSON projectCfg}
|
||||
EOF
|
||||
echo file sotest-binaries $out/binaries.zip >> "$out/nix-support/hydra-build-products"
|
||||
echo file sotest-config $out/project.json >> "$out/nix-support/hydra-build-products"
|
||||
'';
|
||||
};
|
||||
}
|
||||
defaultTestScript = ''
|
||||
start_all()
|
||||
machine.wait_until_serial_output('child "init" exited with exit value 0')
|
||||
'';
|
||||
|
||||
makeTest = with buildPackages;
|
||||
{ prefix, specs, basePkg, makeImage, startVM }:
|
||||
{ name ? "unnamed", testScript ? defaultTestScript,
|
||||
# Skip linting (mainly intended for faster dev cycles)
|
||||
skipLint ? false, ... }@t:
|
||||
|
||||
let
|
||||
testDriverName = "genode-test-driver-${name}";
|
||||
|
||||
buildVM = vmName:
|
||||
{ config, inputs, env ? { }, extraPaths ? [ ] }:
|
||||
let
|
||||
storeTarball = buildPackages.runCommand "store" { } ''
|
||||
mkdir -p $out
|
||||
tar cf "$out/store.tar" --absolute-names ${toString inputs} ${
|
||||
toString extraPaths
|
||||
}
|
||||
'';
|
||||
addManifest = drv:
|
||||
drv // {
|
||||
manifest =
|
||||
nixpkgs.runCommand "${drv.name}.dhall" { inherit drv; } ''
|
||||
set -eu
|
||||
echo -n '[' >> $out
|
||||
find $drv/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out
|
||||
${if builtins.elem "lib" drv.outputs then
|
||||
''
|
||||
find ${drv.lib}/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out''
|
||||
else
|
||||
""}
|
||||
echo -n ']' >> $out
|
||||
'';
|
||||
};
|
||||
|
||||
storeManifest = lib.mergeManifests (map addManifest inputs);
|
||||
manifest = lib.mergeManifests (map addManifest
|
||||
([ basePkg testPkgs.sotest-producer storeTarball ]
|
||||
++ map testPkgs.genodeSources.depot [
|
||||
"init"
|
||||
"rtc_drv"
|
||||
"vfs"
|
||||
"cached_fs_rom"
|
||||
]));
|
||||
config' = "${
|
||||
./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;
|
||||
|
||||
image = makeImage vmName env' config';
|
||||
startVM' = startVM vmName image;
|
||||
in {
|
||||
script = buildPackages.writeScriptBin "run-${vmName}-vm" startVM';
|
||||
|
||||
config = lib.runDhallCommand (name + ".dhall") env' ''
|
||||
${apps.dhall.program} <<< "${config'}" > $out
|
||||
'';
|
||||
|
||||
store = storeTarball;
|
||||
|
||||
xml = lib.runDhallCommand (name + ".config") env'
|
||||
''${apps.render-init.program} <<< "(${config'}).config" > $out'';
|
||||
};
|
||||
|
||||
nodes = lib.mapAttrs buildVM
|
||||
(t.nodes or (if t ? machine then { machine = t.machine; } else { }));
|
||||
|
||||
testScript' =
|
||||
# Call the test script with the computed nodes.
|
||||
if lib.isFunction testScript then
|
||||
testScript { inherit nodes; }
|
||||
else
|
||||
testScript;
|
||||
|
||||
vms = map (node: node.script) (lib.attrValues nodes);
|
||||
|
||||
# Generate onvenience wrappers for running the test driver
|
||||
# interactively with the specified network, and for starting the
|
||||
# VMs from the command line.
|
||||
driver =
|
||||
let warn = if skipLint then lib.warn "Linting is disabled!" else lib.id;
|
||||
in warn (runCommand testDriverName {
|
||||
buildInputs = [ makeWrapper ];
|
||||
testScript = testScript';
|
||||
preferLocalBuild = true;
|
||||
testName = name;
|
||||
} ''
|
||||
mkdir -p $out/bin
|
||||
|
||||
echo -n "$testScript" > $out/test-script
|
||||
${lib.optionalString (!skipLint) ''
|
||||
${python3Packages.black}/bin/black --check --quiet --diff $out/test-script
|
||||
''}
|
||||
|
||||
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/
|
||||
vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done))
|
||||
wrapProgram $out/bin/nixos-test-driver \
|
||||
--add-flags "''${vms[*]}" \
|
||||
--run "export testScript=\"\$(${coreutils}/bin/cat $out/test-script)\""
|
||||
ln -s ${testDriver}/bin/nixos-test-driver $out/bin/nixos-run-vms
|
||||
wrapProgram $out/bin/nixos-run-vms \
|
||||
--add-flags "''${vms[*]}" \
|
||||
--set tests 'start_all(); join_all();'
|
||||
''); # "
|
||||
|
||||
passMeta = drv:
|
||||
drv
|
||||
// lib.optionalAttrs (t ? meta) { meta = (drv.meta or { }) // t.meta; };
|
||||
|
||||
# Run an automated test suite in the given virtual network.
|
||||
# `driver' is the script that runs the network.
|
||||
runTests = driver:
|
||||
stdenv.mkDerivation {
|
||||
name = "test-run-${driver.testName}";
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out
|
||||
|
||||
LOGFILE=/dev/null tests='exec(os.environ["testScript"])' ${driver}/bin/nixos-test-driver
|
||||
'';
|
||||
};
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
|
||||
nodeNames = builtins.attrNames nodes;
|
||||
invalidNodeNames =
|
||||
lib.filter (node: builtins.match "^[A-z_]([A-z0-9_]+)?$" node == null)
|
||||
nodeNames;
|
||||
|
||||
in if lib.length invalidNodeNames > 0 then
|
||||
throw ''
|
||||
Cannot create machines out of (${
|
||||
lib.concatStringsSep ", " invalidNodeNames
|
||||
})!
|
||||
All machines are referenced as python variables in the testing framework which will break the
|
||||
script when special characters are used.
|
||||
|
||||
Please stick to alphanumeric chars and underscores as separation.
|
||||
''
|
||||
else
|
||||
test // { inherit nodes driver test; };
|
||||
|
||||
testList = let
|
||||
f = platform:
|
||||
let makeTest' = makeTest platform;
|
||||
in test:
|
||||
if (test.constraints or (_: true)) platform.specs then {
|
||||
name = platform.prefix + test.name;
|
||||
value = makeTest' test;
|
||||
} else
|
||||
null;
|
||||
|
||||
in lib.lists.crossLists f [ platforms testFiles ];
|
||||
|
||||
in builtins.listToAttrs (builtins.filter (_: _ != null) testList)
|
||||
|
||||
/* sotest = let
|
||||
hwTests = with hw; [ multi posix x86 ];
|
||||
novaTests = with nova; [ multi posix x86 vmm ];
|
||||
allTests = hwTests ++ novaTests;
|
||||
|
||||
projectCfg.boot_items =
|
||||
|
||||
(map (test: {
|
||||
inherit (test) name;
|
||||
exec = "bender";
|
||||
load = [ "${test.name}.image.elf" ];
|
||||
}) hwTests)
|
||||
|
||||
++ (map (test: {
|
||||
inherit (test) name;
|
||||
exec = "bender";
|
||||
load = [ "hypervisor serial novga iommu" test.image.name ];
|
||||
}) novaTests);
|
||||
|
||||
in buildPackages.stdenv.mkDerivation {
|
||||
name = "sotest";
|
||||
buildCommand = ''
|
||||
mkdir zip; cd zip
|
||||
cp "${testPkgs.bender}/bender" bender
|
||||
cp "${testPkgs.NOVA}/hypervisor-x86_64" hypervisor
|
||||
${concatStringsSep "\n"
|
||||
(map (test: "cp ${test.image}/image.elf ${test.name}.image.elf")
|
||||
allTests)}
|
||||
mkdir -p $out/nix-support
|
||||
${buildPackages.zip}/bin/zip "$out/binaries.zip" *
|
||||
cat << EOF > "$out/project.json"
|
||||
${builtins.toJSON projectCfg}
|
||||
EOF
|
||||
echo file sotest-binaries $out/binaries.zip >> "$out/nix-support/hydra-build-products"
|
||||
echo file sotest-config $out/project.json >> "$out/nix-support/hydra-build-products"
|
||||
'';
|
||||
};
|
||||
*/
|
||||
|
@ -1,173 +0,0 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ addManifest, apps, buildPackages, lib, nixpkgs, testPkgs, legacyPackages }:
|
||||
|
||||
let
|
||||
testDriver = with buildPackages;
|
||||
stdenv.mkDerivation {
|
||||
name = "hw-genode-test-driver";
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildInputs = [ makeWrapper expect ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
installPhase = ''
|
||||
install -Dm555 ${./hw-test-driver.exp} $out/bin/genode-test-driver
|
||||
wrapProgram $out/bin/genode-test-driver \
|
||||
--prefix PATH : "${lib.makeBinPath [ expect coreutils ]}"
|
||||
'';
|
||||
};
|
||||
|
||||
runTests = driver:
|
||||
buildPackages.stdenv.mkDerivation {
|
||||
name = "hw-" + driver.testName;
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
${driver}/bin/genode-test-driver | tee $out/log
|
||||
|
||||
touch $out/nix-support
|
||||
echo "report testlog $out log" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
|
||||
defaultScript =
|
||||
''run_genode_until {child "init" exited with exit value 0} 120'';
|
||||
|
||||
mkTest = { name ? "unamed", testScript ? defaultScript, testConfig
|
||||
, testInputs ? [ ], testEnv ? { }, extraPaths ? [ ], qemuArgs ? [ ], ...
|
||||
}@t:
|
||||
let
|
||||
storeTarball = buildPackages.runCommand "store" { } ''
|
||||
mkdir -p $out
|
||||
tar cf "$out/store.tar" --absolute-names ${toString testInputs} ${
|
||||
toString extraPaths
|
||||
}
|
||||
'';
|
||||
storeManifest = lib.mergeManifests (map addManifest testInputs);
|
||||
manifest = lib.mergeManifests (map addManifest
|
||||
([ testPkgs.base-hw-pc testPkgs.sotest-producer storeTarball ]
|
||||
++ map testPkgs.genodeSources.depot [
|
||||
"init"
|
||||
"rtc_drv"
|
||||
"vfs"
|
||||
"cached_fs_rom"
|
||||
]));
|
||||
testConfig' = "${
|
||||
./test-wrapper.dhall
|
||||
} (${testConfig}) $(stat --format '%s' ${storeTarball}/store.tar) ${storeManifest} ${manifest}";
|
||||
testEnv' = {
|
||||
DHALL_GENODE = "${testPkgs.dhallGenode}/source.dhall";
|
||||
DHALL_GENODE_TEST = "${./test.dhall}";
|
||||
} // testEnv;
|
||||
|
||||
image = lib.hwImage ("hw-" + name) testEnv' testConfig';
|
||||
|
||||
baseSetup = ''
|
||||
##
|
||||
# Wait for a specific output of a already running spawned proce
|
||||
#
|
||||
proc wait_for_output { wait_for_re timeout_value running_spawn_id } {
|
||||
global output
|
||||
|
||||
if {$wait_for_re == "forever"} {
|
||||
set timeout -1
|
||||
interact {
|
||||
\003 {
|
||||
send_user "Expect: 'interact' received 'strg+c' and was cancelled\n";
|
||||
exit
|
||||
}
|
||||
-i $running_spawn_id
|
||||
}
|
||||
} else {
|
||||
set timeout $timeout_value
|
||||
}
|
||||
|
||||
expect {
|
||||
-i $running_spawn_id -re $wait_for_re { }
|
||||
eof { puts stderr "Error: Spawned process died unexpectedly"; exit -1 }
|
||||
timeout { puts stderr "Error: Test execution timed out"; exit -1 }
|
||||
}
|
||||
set output $expect_out(buffer)
|
||||
}
|
||||
|
||||
proc run_genode_until {{wait_for_re forever} {timeout_value 0} {running_spawn_id -1}} {
|
||||
#
|
||||
# If a running_spawn_id is specified, wait for the expected output
|
||||
#
|
||||
if {$running_spawn_id != -1} {
|
||||
wait_for_output $wait_for_re $timeout_value $running_spawn_id
|
||||
return
|
||||
}
|
||||
|
||||
global env
|
||||
global spawn_id
|
||||
set TEST_MIB [expr (([file size ${image}/image.elf] + $env(TEST_RAM)) >> 20) + 24]
|
||||
spawn ${buildPackages.qemu_test}/bin/qemu-system-x86_64 \
|
||||
-machine q35 -serial mon:stdio -nographic \
|
||||
-m size=$TEST_MIB \
|
||||
-kernel "${testPkgs.bender}/bender" \
|
||||
-initrd "${image}/image.elf" \
|
||||
${toString qemuArgs}
|
||||
wait_for_output $wait_for_re $timeout_value $spawn_id
|
||||
}
|
||||
|
||||
# TODO: not in TCL
|
||||
global env
|
||||
set out $env(out)
|
||||
'';
|
||||
|
||||
driver = with buildPackages;
|
||||
buildPackages.runCommand "genode-test-driver-${name}" ({
|
||||
buildInputs = [ makeWrapper expect ];
|
||||
inherit baseSetup testScript;
|
||||
preferLocalBuild = true;
|
||||
testName = name;
|
||||
} // testEnv') ''
|
||||
mkdir -p $out/bin
|
||||
echo "$testScript" > $out/test-script
|
||||
echo "$baseSetup" > $out/base-setup
|
||||
source ${image.build}/stats
|
||||
|
||||
ln -s ${testDriver}/bin/genode-test-driver $out/bin/
|
||||
wrapProgram $out/bin/genode-test-driver \
|
||||
--set testScript "$testScript" \
|
||||
--set baseSetup "$baseSetup" \
|
||||
--set TEST_RAM $RAM \
|
||||
'';
|
||||
|
||||
passMeta = drv:
|
||||
drv
|
||||
// lib.optionalAttrs (t ? meta) { meta = (drv.meta or { }) // t.meta; };
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
|
||||
in test // {
|
||||
inherit driver image test manifest;
|
||||
|
||||
config = buildPackages.runCommand (name + ".dhall") testEnv' ''
|
||||
${apps.dhall.program} <<< "${testConfig'}" > $out
|
||||
'';
|
||||
|
||||
iso = apps.hw-iso.function testEnv' testConfig';
|
||||
|
||||
xml = buildPackages.runCommand (name + ".config") testEnv'
|
||||
''${apps.render-init.program} <<< "(${testConfig'}).config" > $out'';
|
||||
|
||||
};
|
||||
|
||||
in {
|
||||
callTest = path: args:
|
||||
(import path ({
|
||||
testEnv = {
|
||||
inherit mkTest lib;
|
||||
isLinux = false;
|
||||
isNova = true;
|
||||
};
|
||||
pkgs = testPkgs;
|
||||
inherit nixpkgs buildPackages legacyPackages;
|
||||
} // args));
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ addManifest, apps, buildPackages, lib, nixpkgs, testPkgs, legacyPackages }:
|
||||
|
||||
let
|
||||
testDriver = with buildPackages;
|
||||
stdenv.mkDerivation {
|
||||
name = "nova-genode-test-driver";
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildInputs = [ makeWrapper expect ];
|
||||
|
||||
dontUnpack = true;
|
||||
|
||||
installPhase = ''
|
||||
install -Dm555 ${./nova-test-driver.exp} $out/bin/genode-test-driver
|
||||
wrapProgram $out/bin/genode-test-driver \
|
||||
--prefix PATH : "${lib.makeBinPath [ expect coreutils ]}"
|
||||
'';
|
||||
};
|
||||
|
||||
runTests = driver:
|
||||
buildPackages.stdenv.mkDerivation {
|
||||
name = "nova-" + driver.testName;
|
||||
preferLocalBuild = true;
|
||||
|
||||
buildCommand = ''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
${driver}/bin/genode-test-driver | tee $out/log
|
||||
|
||||
touch $out/nix-support
|
||||
echo "report testlog $out log" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
|
||||
defaultScript =
|
||||
''run_genode_until {child "init" exited with exit value 0} 120'';
|
||||
|
||||
mkTest = { name ? "unamed", testScript ? defaultScript, testConfig
|
||||
, testInputs ? [ ], testEnv ? { }, extraPaths ? [ ], qemuArgs ? [ ], ...
|
||||
}@t:
|
||||
let
|
||||
storeTarball = buildPackages.runCommand "store" { } ''
|
||||
mkdir -p $out
|
||||
tar cf "$out/store.tar" --absolute-names ${toString testInputs} ${
|
||||
toString extraPaths
|
||||
}
|
||||
'';
|
||||
storeManifest = lib.mergeManifests (map addManifest testInputs);
|
||||
manifest = lib.mergeManifests (map addManifest
|
||||
([ testPkgs.base-nova testPkgs.sotest-producer storeTarball ]
|
||||
++ map testPkgs.genodeSources.depot [
|
||||
"init"
|
||||
"rtc_drv"
|
||||
"vfs"
|
||||
"cached_fs_rom"
|
||||
]));
|
||||
testConfig' = "${
|
||||
./test-wrapper.dhall
|
||||
} (${testConfig}) $(stat --format '%s' ${storeTarball}/store.tar) ${storeManifest} ${manifest}";
|
||||
testEnv' = {
|
||||
DHALL_GENODE = "${testPkgs.dhallGenode}/source.dhall";
|
||||
DHALL_GENODE_TEST = "${./test.dhall}";
|
||||
} // testEnv;
|
||||
|
||||
image = lib.novaImage ("nova-" + name) testEnv' testConfig';
|
||||
build = lib.compileBoot name testEnv' testConfig';
|
||||
|
||||
baseSetup = ''
|
||||
##
|
||||
# Wait for a specific output of a already running spawned proce
|
||||
#
|
||||
proc wait_for_output { wait_for_re timeout_value running_spawn_id } {
|
||||
global output
|
||||
|
||||
if {$wait_for_re == "forever"} {
|
||||
set timeout -1
|
||||
interact {
|
||||
\003 {
|
||||
send_user "Expect: 'interact' received 'strg+c' and was cancelled\n";
|
||||
exit
|
||||
}
|
||||
-i $running_spawn_id
|
||||
}
|
||||
} else {
|
||||
set timeout $timeout_value
|
||||
}
|
||||
|
||||
expect {
|
||||
-i $running_spawn_id -re $wait_for_re { }
|
||||
eof { puts stderr "Error: Spawned process died unexpectedly"; exit -1 }
|
||||
timeout { puts stderr "Error: Test execution timed out"; exit -1 }
|
||||
}
|
||||
set output $expect_out(buffer)
|
||||
}
|
||||
|
||||
proc run_genode_until {{wait_for_re forever} {timeout_value 0} {running_spawn_id -1}} {
|
||||
#
|
||||
# If a running_spawn_id is specified, wait for the expected output
|
||||
#
|
||||
if {$running_spawn_id != -1} {
|
||||
wait_for_output $wait_for_re $timeout_value $running_spawn_id
|
||||
return
|
||||
}
|
||||
|
||||
global env
|
||||
global spawn_id
|
||||
set TEST_MIB [expr (([file size ${image}/image.elf] + $env(TEST_RAM)) >> 20) + 24]
|
||||
spawn ${buildPackages.qemu_test}/bin/qemu-system-x86_64 \
|
||||
-machine q35 -cpu phenom -smp 2 \
|
||||
-serial mon:stdio -nographic \
|
||||
-m size=$TEST_MIB \
|
||||
-kernel "${testPkgs.bender}/bender" \
|
||||
-initrd "${testPkgs.NOVA}/hypervisor-x86_64 arg=iommu novpid serial,${image}/image.elf" \
|
||||
${toString qemuArgs}
|
||||
wait_for_output $wait_for_re $timeout_value $spawn_id
|
||||
}
|
||||
|
||||
# TODO: not in TCL
|
||||
global env
|
||||
set out $env(out)
|
||||
'';
|
||||
|
||||
driver = with buildPackages;
|
||||
buildPackages.runCommand "genode-test-driver-${name}" ({
|
||||
buildInputs = [ makeWrapper expect ];
|
||||
inherit baseSetup testScript;
|
||||
preferLocalBuild = true;
|
||||
testName = name;
|
||||
} // testEnv') ''
|
||||
mkdir -p $out/bin
|
||||
echo "$testScript" > $out/test-script
|
||||
echo "$baseSetup" > $out/base-setup
|
||||
source ${image.build}/stats
|
||||
|
||||
ln -s ${testDriver}/bin/genode-test-driver $out/bin/
|
||||
wrapProgram $out/bin/genode-test-driver \
|
||||
--set testScript "$testScript" \
|
||||
--set baseSetup "$baseSetup" \
|
||||
--set TEST_RAM $RAM \
|
||||
'';
|
||||
|
||||
passMeta = drv:
|
||||
drv
|
||||
// lib.optionalAttrs (t ? meta) { meta = (drv.meta or { }) // t.meta; };
|
||||
|
||||
test = passMeta (runTests driver);
|
||||
|
||||
in test // {
|
||||
inherit driver image test manifest;
|
||||
inherit (image) build;
|
||||
|
||||
config = buildPackages.runCommand (name + ".dhall") testEnv' ''
|
||||
${apps.dhall.program} <<< "${testConfig'}" > $out
|
||||
'';
|
||||
|
||||
compile = lib.compileBoot name testConfig';
|
||||
|
||||
iso = apps.nova-iso.function testEnv' "${testConfig'}";
|
||||
|
||||
store = storeTarball;
|
||||
|
||||
xml = buildPackages.runCommand (name + ".config") testEnv'
|
||||
''${apps.render-init.program} <<< "(${testConfig'}).config" > $out'';
|
||||
};
|
||||
|
||||
in {
|
||||
callTest = path: args:
|
||||
(import path ({
|
||||
testEnv = {
|
||||
inherit mkTest lib;
|
||||
isLinux = false;
|
||||
isNova = true;
|
||||
};
|
||||
pkgs = testPkgs;
|
||||
inherit nixpkgs buildPackages legacyPackages;
|
||||
} // args));
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ testEnv, pkgs, buildPackages, ... }:
|
||||
with pkgs;
|
||||
|
||||
testEnv.mkTest {
|
||||
name = "driver_manager";
|
||||
meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ehmry ];
|
||||
testEnv = { drivers = ./../compositions/pc-drivers.dhall; };
|
||||
testInputs = (map pkgs.genodeSources.depot [
|
||||
"acpi_drv"
|
||||
"ahci_drv"
|
||||
"boot_fb_drv"
|
||||
"driver_manager"
|
||||
"dynamic_rom"
|
||||
"input_filter"
|
||||
"intel_fb_drv"
|
||||
"platform_drv"
|
||||
"ps2_drv"
|
||||
"report_rom"
|
||||
"rom_reporter"
|
||||
"usb_drv"
|
||||
"vesa_drv"
|
||||
]) ++ (map pkgs.genodeSources.make [ "test/driver_manager" ]);
|
||||
|
||||
testScript = ''
|
||||
catch { exec dd if=/dev/zero of=hdd_disk.raw bs=1M count=32 }
|
||||
catch { exec ${buildPackages.e2fsprogs}/bin/mke2fs -F bin/hdd_disk.raw }
|
||||
run_genode_until {.*all expected devices present and accessible.*} 120
|
||||
'';
|
||||
testConfig = ./driver_manager.dhall;
|
||||
qemuArgs = [
|
||||
"-device ahci,id=ahci"
|
||||
"-drive id=hdd,file=hdd_disk.raw,format=raw,if=none"
|
||||
"-device ide-hd,drive=hdd,bus=ahci.1"
|
||||
];
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ testEnv, pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
with pkgs;
|
||||
|
||||
testEnv.mkTest rec {
|
||||
{
|
||||
name = "log";
|
||||
meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ehmry ];
|
||||
|
||||
testConfig = ./log.dhall;
|
||||
testInputs = [ (pkgs.genodeSources.depot "test-log") ];
|
||||
testScript = "run_genode_until {Test done.} 120";
|
||||
machine = {
|
||||
config = ./log.dhall;
|
||||
inputs = [ (pkgs.genodeSources.depot "test-log") ];
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_until_serial_output("Test done.")
|
||||
'';
|
||||
}
|
||||
|
@ -1,46 +1,44 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
{ testEnv, pkgs, ... }:
|
||||
{ pkgs, ... }:
|
||||
with pkgs;
|
||||
|
||||
let
|
||||
mkTest' = { name, testConfig, testInputs ? [ ], ... }@attrs:
|
||||
testEnv.mkTest (attrs // {
|
||||
solo5Test = { name, machine, ... }@args:
|
||||
args // {
|
||||
name = "solo5-" + name;
|
||||
inherit testConfig;
|
||||
testInputs = [ pkgs.solo5 pkgs.solo5.tests ] ++ testInputs;
|
||||
});
|
||||
|
||||
applyMkTest = x: {
|
||||
inherit (x) name;
|
||||
value = mkTest' x;
|
||||
};
|
||||
|
||||
mkTests = testList: builtins.listToAttrs (map applyMkTest testList);
|
||||
machine = machine // {
|
||||
inputs = [ pkgs.solo5 pkgs.solo5.tests ] ++ machine.inputs;
|
||||
};
|
||||
};
|
||||
|
||||
genodeDepot = pkgs.genodeSources.depot;
|
||||
genodeMake = pkgs.genodeSources.make;
|
||||
|
||||
tests = [
|
||||
{
|
||||
name = "multi";
|
||||
testConfig = "${./.}/solo5.dhall";
|
||||
testInputs = map genodeMake [ "app/ping" ] ++ (map genodeDepot [
|
||||
in map solo5Test [
|
||||
{
|
||||
name = "multi";
|
||||
machine = {
|
||||
config = "${./.}/solo5.dhall";
|
||||
inputs = map genodeMake [ "app/ping" ] ++ (map genodeDepot [
|
||||
"ram_block"
|
||||
"nic_bridge"
|
||||
"nic_loopback"
|
||||
"sequence"
|
||||
]);
|
||||
}
|
||||
|
||||
{
|
||||
name = "ssp";
|
||||
testConfig = ./ssp.dhall;
|
||||
testScript = ''
|
||||
run_genode_until {Error: stack protector check failed} 30
|
||||
'';
|
||||
}
|
||||
|
||||
];
|
||||
|
||||
in mkTests tests
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
name = "ssp";
|
||||
machine = {
|
||||
config = ./ssp.dhall;
|
||||
inputs = [ ];
|
||||
};
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.wait_until_serial_output("Error: stack protector check failed")
|
||||
'';
|
||||
}
|
||||
|
||||
]
|
||||
|