# SPDX-FileCopyrightText: Emery Hemingway # # SPDX-License-Identifier: LicenseRef-Hippocratic-1.1 { testPkgs, hostPkgs, lib }: let testDriver = with hostPkgs; stdenv.mkDerivation { name = "nova-genode-test-driver"; buildInputs = [ makeWrapper expect ]; dontUnpack = true; preferLocalBuild = 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: hostPkgs.stdenv.mkDerivation { name = "test-run-${driver.testName}"; 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 ''; }; makeTest = { testScript, testConfig, name ? "unamed", ... }@t: let baseSetup = with testPkgs; '' source ${./common-test-driver.exp} global modules set HOSTLD ${buildPackages.binutils}/bin/x86_64-unknown-genode-elf-ld file link -s timer ${genode.base-nova}/bin/nova_timer_drv file link -s ld.lib.so ${depot.base-nova}/lib/ld.lib.so file link -s core-nova.o ${depot.base-nova}/lib/core-nova.o file link -s init ${genode.os}/bin/init file link -s config ${./driver-config.xml} file link -s test.config $env(testConfig) set modules { timer ld.lib.so init config test.config } set qemu_mem 64 ## # Link core image containing given modules # proc build_core {lib modules target} { global env # generate assembly code aggregating the modules data set asm_src [generate_boot_modules_asm $modules] # compile the boot modules into one object file exec $env(CC) -c -x assembler -o boot_modules.o - << $asm_src # link final image global HOSTLD exec $HOSTLD -nostdlib \ -T${./genode.ld} \ -T${./nova-bss.ld} \ -z max-page-size=0x1000 \ -Ttext=0x100000 -gc-sections \ --whole-archive \ $lib boot_modules.o --no-whole-archive \ -o $target } proc build_iso {target} { # TODO: take our own build of NOVA file mkdir boot/syslinux file copy ${nova}/hypervisor-x86_64 boot/hypervisor file copy ${./nova-isolinux.cfg} boot/syslinux/isolinux.cfg file copy ${hostPkgs.syslinux}/share/syslinux/isolinux.bin boot/syslinux/isolinux.bin file copy ${hostPkgs.syslinux}/share/syslinux/ldlinux.c32 boot/syslinux/ldlinux.c32 file copy ${hostPkgs.syslinux}/share/syslinux/libcom32.c32 boot/syslinux/libcom32.c32 file copy ${hostPkgs.syslinux}/share/syslinux/mboot.c32 boot/syslinux/mboot.c32 exec chmod +w boot/syslinux/isolinux.bin catch { exec ${hostPkgs.cdrkit}/bin/mkisofs -o $target \ -b syslinux/isolinux.bin -c syslinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ -iso-level 2 \ boot } puts "built ISO?" } ## # Wait for a specific output of a already running spawned process # 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 modules qemu_mem file mkdir boot build_core core-nova.o $modules boot/image.elf set out $env(out) build_iso $out/test.iso global spawn_id spawn ${hostPkgs.qemu_test}/bin/qemu-system-x86_64 -cdrom $out/test.iso -nographic -m $qemu_mem wait_for_output $wait_for_re $timeout_value $spawn_id } ''; driver = with hostPkgs; buildPackages.runCommand "genode-test-driver-${name}" { buildInputs = [ makeWrapper expect ]; inherit baseSetup testConfig testScript; preferLocalBuild = true; testName = name; } '' mkdir -p $out/bin echo "$testConfig" > $out/test.config echo "$testScript" > $out/test-script echo "$baseSetup" > $out/base-setup ln -s ${testDriver}/bin/genode-test-driver $out/bin/ wrapProgram $out/bin/genode-test-driver \ --run "export testConfig=\"$testConfig\"" \ --run "export testScript=\"\$(cat $out/test-script)\"" \ --run "export baseSetup=\"\$(cat $out/base-setup)\"" \ ''; passMeta = drv: drv // lib.optionalAttrs (t ? meta) { meta = (drv.meta or { }) // t.meta; }; test = passMeta (runTests driver); in test // { inherit driver test; }; in { callTest = path: args: makeTest (import path ({ pkgs = testPkgs; inherit lib; } // args)); }