# 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)); }