From a3f8d20d231f34254fa45d65969d96c348f32df2 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Thu, 10 Oct 2019 10:28:19 +0200 Subject: [PATCH] Tests: replace most of the Tcl code Tcl is awful. Generate NOVA test ISOs with a shell script derivation. --- tests/default.nix | 7 +- tests/driver-config.xml | 2 +- tests/driver-linux.nix | 27 ++++--- tests/driver-nova.nix | 173 ++++++++++++++-------------------------- tests/fs_report.nix | 14 ++-- tests/libc.nix | 19 +++-- tests/log.nix | 7 +- tests/nova-iso.nix | 100 +++++++++++++++++++++++ tests/signal.nix | 8 +- tests/solo5-ping.dhall | 10 +-- tests/solo5-ping.nix | 14 ++-- tests/solo5.dhall | 38 ++++----- tests/solo5.nix | 19 +++-- 13 files changed, 249 insertions(+), 189 deletions(-) create mode 100644 tests/nova-iso.nix diff --git a/tests/default.nix b/tests/default.nix index 4423a4e..1c6bc8d 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -11,12 +11,9 @@ let solo5 = call ./solo5.nix { }; solo5-ping = call ./solo5-ping.nix { }; }; -in -{ genodepkgs ? import ./../default.nix { } -, nixpkgs ? import ./../nixpkgs.nix -, dhall-haskell -}: +in { genodepkgs ? import ./../default.nix { }, nixpkgs ? import ./../nixpkgs.nix +, dhall-haskell }: let hostPkgs = import nixpkgs { diff --git a/tests/driver-config.xml b/tests/driver-config.xml index 373fbed..3f70ca6 100644 --- a/tests/driver-config.xml +++ b/tests/driver-config.xml @@ -27,7 +27,7 @@ - + diff --git a/tests/driver-linux.nix b/tests/driver-linux.nix index 70bf088..e05052a 100644 --- a/tests/driver-linux.nix +++ b/tests/driver-linux.nix @@ -36,19 +36,26 @@ let ''; }; - makeTest = { testScript, testConfig, name ? "unamed", ... }@t: + makeTest = { name ? "unamed", testScript, testConfig, bootModules, ... }@t: + with testPkgs; let + bootModules' = { + inherit testConfig; + config = ./driver-config.xml; + core = "${depot.base-linux}/bin/core"; + init = "${genode.os}/bin/init"; + "ld.lib.so" = "${depot.base-linux}/lib/ld.lib.so"; + timer = "${genode.base-linux}/bin/linux_timer_drv"; + } // bootModules; - baseSetup = with testPkgs; '' - source ${./common-test-driver.exp} + baseSetup = with builtins; + lib.concatStrings (map (name: '' + file link -s ${name} ${getAttr name bootModules'} + '') (attrNames bootModules')) - file link -s core ${depot.base-linux}/bin/core - file link -s timer ${genode.base-linux}/bin/linux_timer_drv - file link -s ld.lib.so ${depot.base-linux}/lib/ld.lib.so - file link -s init ${genode.os}/bin/init - file link -s config ${./driver-config.xml} - file link -s test.config $env(testConfig) - ''; + + '' + source ${./common-test-driver.exp} + ''; driver = with hostPkgs; runCommand "genode-test-driver-${name}" { diff --git a/tests/driver-nova.nix b/tests/driver-nova.nix index 1182ab0..8ca39a1 100644 --- a/tests/driver-nova.nix +++ b/tests/driver-nova.nix @@ -36,129 +36,74 @@ let ''; }; - makeTest = { testScript, testConfig, name ? "unamed", ... }@t: + mkIso = import ./nova-iso.nix { + inherit hostPkgs testPkgs; + coreNovaObj = "${testPkgs.depot.base-nova}/lib/core-nova.o"; + }; + + makeTest = { name ? "unamed", testScript, testConfig, bootModules + , qemuMem ? 32, ... }@t: let + iso = mkIso (with testPkgs; + { + inherit testConfig; + config = ./driver-config.xml; + init = "${genode.os}/bin/init"; + "ld.lib.so" = "${depot.base-nova}/lib/ld.lib.so"; + timer = "${genode.base-nova}/bin/nova_timer_drv"; + } // bootModules); - baseSetup = with testPkgs; + 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 - '' - source ${./common-test-driver.exp} - global modules - set HOSTLD ${buildPackages.binutils}/bin/x86_64-unknown-genode-elf-ld + 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 + } - 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 - } - } - - ## - # 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) - } + 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 - } + 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 + global env + set out $env(out) - set out $env(out) - build_iso $out/test.iso + set fd [open "$out/nix-support/hydra-build-products" w] + puts $fd "file iso ${iso}" + close $fd - set fd [open "$out/nix-support/hydra-build-products" w] - puts $fd "file iso $out/test.iso" - close $fd - - 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 - } - ''; + global spawn_id + spawn ${hostPkgs.qemu_test}/bin/qemu-system-x86_64 -cdrom ${iso} -nographic \ + -m size=${toString qemuMem} + wait_for_output $wait_for_re $timeout_value $spawn_id + } + ''; driver = with hostPkgs; buildPackages.runCommand "genode-test-driver-${name}" { diff --git a/tests/fs_report.nix b/tests/fs_report.nix index e8b6985..e2f0447 100644 --- a/tests/fs_report.nix +++ b/tests/fs_report.nix @@ -7,13 +7,15 @@ with pkgs; testConfig = ./fs_report.xml; - testScript = '' - collect_modules ${depot.fs_report}/bin/* - collect_modules ${depot.fs_rom}/bin/* - collect_modules ${depot.ram_fs}/bin/* - collect_modules ${depot.test-fs_report}/bin/* - collect_modules ${depot.vfs}/lib/* + bootModules = { + fs_report = "${depot.fs_report}/bin/fs_report"; + fs_rom = "${depot.fs_rom}/bin/fs_rom"; + ram_fs = "${depot.ram_fs}/bin/ram_fs"; + test-fs_report = "${depot.test-fs_report}/bin/test-fs_report"; + "vfs.lib.so" = "${depot.vfs}/lib/vfs.lib.so"; + }; + testScript = '' run_genode_until {child "test-fs_report" exited with exit value 0} 15 ''; } diff --git a/tests/libc.nix b/tests/libc.nix index ea0b0ee..d10b28f 100644 --- a/tests/libc.nix +++ b/tests/libc.nix @@ -5,16 +5,19 @@ rec { name = "libc"; meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ehmry ]; - testConfig = lib.renderDhallInit ./libc.dhall "{=}"; + testConfig = lib.renderDhallInit ./libc.dhall "{=}"; + + bootModules = { + "libc.lib.so" = "${depot.libc}/lib/libc.lib.so"; + "libm.lib.so" = "${depot.libc}/lib/libm.lib.so"; + "posix.lib.so" = "${depot.posix}/lib/posix.lib.so"; + "test-libc" = "${depot.test-libc}/bin/test-libc"; + "vfs.lib.so" = "${depot.vfs}/lib/vfs.lib.so"; + }; + + qemuMem = 384; testScript = '' - global qemu_mem - collect_modules ${depot.libc}/lib/* - collect_modules ${depot.posix}/lib/* - collect_modules ${depot.test-libc}/bin/* - collect_modules ${depot.vfs}/lib/* - - set qemu_mem 384 run_genode_until "child .* exited with exit value 0.*\n" 30 ''; } diff --git a/tests/log.nix b/tests/log.nix index 5226804..d1c4e3b 100644 --- a/tests/log.nix +++ b/tests/log.nix @@ -7,8 +7,7 @@ rec { testConfig = lib.renderDhallInit ./log.dhall "{=}"; - testScript = '' - collect_modules ${depot.test-log}/bin/* - run_genode_until {Test done.} 10 - ''; + bootModules.test-log = "${depot.test-log}/bin/test-log"; + + testScript = "run_genode_until {Test done.} 10"; } diff --git a/tests/nova-iso.nix b/tests/nova-iso.nix new file mode 100644 index 0000000..fdac305 --- /dev/null +++ b/tests/nova-iso.nix @@ -0,0 +1,100 @@ +# SPDX-FileCopyrightText: Emery Hemingway +# +# SPDX-License-Identifier: LicenseRef-Hippocratic-1.1 + +{ hostPkgs, testPkgs, coreNovaObj }: +modules: + +let + inherit (hostPkgs) lib cdrkit syslinux; + + addressType = ".quad"; # TODO: 32 or 64 bit?! + + map' = l: f: lib.concatStrings (lib.imap0 (i: v: (f (toString i) v)) l); + + mapNames = map' (builtins.attrNames modules); + mapValues = map' (builtins.attrValues modules); + + modulesAsm = '' + .set MIN_PAGE_SIZE_LOG2, 12 + .set DATA_ACCESS_ALIGNM_LOG2, 3 + + .section .data + + .p2align DATA_ACCESS_ALIGNM_LOG2 + .global _boot_modules_headers_begin + _boot_modules_headers_begin: + + '' + (mapNames (i: _: '' + ${addressType} _boot_module_${i}_name + ${addressType} _boot_module_${i}_begin + ${addressType} _boot_module_${i}_end - _boot_module_${i}_begin + + '')) + '' + .global _boot_modules_headers_end + _boot_modules_headers_end: + + '' + (mapNames (i: name: '' + .p2align DATA_ACCESS_ALIGNM_LOG2 + _boot_module_${i}_name: + .string "${name}" + .byte 0 + + '')) + '' + .section .data.boot_modules_binaries + + .global _boot_modules_binaries_begin + _boot_modules_binaries_begin: + + '' + (mapValues (i: path: '' + .p2align MIN_PAGE_SIZE_LOG2 + _boot_module_${i}_begin: + .incbin "${path}" + _boot_module_${i}_end: + + '')) + '' + .p2align MIN_PAGE_SIZE_LOG2 + .global _boot_modules_binaries_end + _boot_modules_binaries_end: + ''; + + syslinuxDir = "${syslinux}/share/syslinux"; + +in hostPkgs.stdenv.mkDerivation { + name = "nova-genode.iso"; + buildInputs = [ testPkgs.stdenv.cc hostPkgs.cdrkit ]; + dontUnpack = true; + dontConfigure = true; + dontBuild = true; + installPhase = '' + mkdir -p boot/syslinux + + # compile the boot modules into one object file + echo '${modulesAsm}' | $CC -c -x assembler -o boot_modules.o - + + # link final image + $LD -nostdlib \ + -T${./genode.ld} \ + -T${./nova-bss.ld} \ + -z max-page-size=0x1000 \ + -Ttext=0x100000 -gc-sections \ + ${coreNovaObj} boot_modules.o \ + -o boot/image.elf + + # build ISO image + cp ${testPkgs.nova}/hypervisor* boot/hypervisor + cp ${./nova-isolinux.cfg} boot/syslinux/isolinux.cfg + cp \ + ${syslinuxDir}/isolinux.bin \ + ${syslinuxDir}/ldlinux.c32 \ + ${syslinuxDir}/libcom32.c32 \ + ${syslinuxDir}/mboot.c32 \ + boot/syslinux + chmod +w boot/syslinux/isolinux.bin + mkisofs -o $out \ + -b syslinux/isolinux.bin -c syslinux/boot.cat \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + -iso-level 2 \ + boot + ''; +} diff --git a/tests/signal.nix b/tests/signal.nix index f17c31f..6ab902d 100644 --- a/tests/signal.nix +++ b/tests/signal.nix @@ -5,11 +5,9 @@ rec { name = "signal"; meta.maintainers = with pkgs.stdenv.lib.maintainers; [ ehmry ]; - testConfig = lib.renderDhallInit ./signal.dhall "{=}"; + testConfig = lib.renderDhallInit ./signal.dhall "{=}"; - testScript = '' - collect_modules ${depot.test-signal}/bin/* + bootModules.test-signal = "${depot.test-signal}/bin/test-signal"; - run_genode_until {--- Signalling test finished ---} 80 - ''; + testScript = "run_genode_until {--- Signalling test finished ---} 120"; } diff --git a/tests/solo5-ping.dhall b/tests/solo5-ping.dhall index d9d9bd1..d8240db 100644 --- a/tests/solo5-ping.dhall +++ b/tests/solo5-ping.dhall @@ -7,14 +7,14 @@ in λ(_ : {}) , bridge = Genode.Init.Start.defaults ⫽ { binary = "nic_bridge" - , resources = { caps = 200, ram = Genode.units.MiB 8 } + , resources = { caps = 200, ram = Genode.units.MiB 6 } , provides = [ "Nic" ] , routes = [ Genode.ServiceRoute.child "Nic" "nic" ] , config = Genode.Prelude.XML.text '' - - + + '' @@ -22,7 +22,7 @@ in λ(_ : {}) , ping_serve = Genode.Init.Start.defaults ⫽ { binary = "solo5-test_net" - , resources = { caps = 256, ram = Genode.units.MiB 4 } + , resources = { caps = 256, ram = Genode.units.MiB 3 } , routes = [ Genode.ServiceRoute.parent "Timer" , Genode.ServiceRoute.child "Nic" "bridge" @@ -36,7 +36,7 @@ in λ(_ : {}) , ping = Genode.Init.Start.defaults ⫽ { binary = "ping" - , resources = { caps = 128, ram = Genode.units.MiB 8 } + , resources = { caps = 128, ram = Genode.units.MiB 6 } , routes = [ Genode.ServiceRoute.parent "Timer" , Genode.ServiceRoute.child "Nic" "bridge" diff --git a/tests/solo5-ping.nix b/tests/solo5-ping.nix index 8e3a2cb..ea61554 100644 --- a/tests/solo5-ping.nix +++ b/tests/solo5-ping.nix @@ -7,13 +7,15 @@ rec { testConfig = lib.renderDhallInit ./solo5-ping.dhall "{=}"; - testScript = '' - collect_modules ${solo5.tests}/bin/solo5-test_net - collect_modules ${solo5}/lib/solo5-bindings-genode/solo5.lib.so - collect_modules ${genode.os}/bin/nic_loopback - collect_modules ${genode.os}/bin/nic_bridge - collect_modules ${genode.os}/bin/ping + bootModules = { + nic_bridge = "${genode.os}/bin/nic_bridge"; + nic_loopback = "${genode.os}/bin/nic_loopback"; + ping = "${genode.os}/bin/ping"; + "solo5.lib.so" = "${solo5}/lib/solo5-bindings-genode/solo5.lib.so"; + solo5-test_net = "${solo5.tests}/bin/solo5-test_net"; + }; + testScript = '' run_genode_until {child "ping" exited with exit value 0} 30 ''; } diff --git a/tests/solo5.dhall b/tests/solo5.dhall index 10c7b4f..f51c8db 100644 --- a/tests/solo5.dhall +++ b/tests/solo5.dhall @@ -18,28 +18,28 @@ in λ(_ : {}) , test = Genode.Init.Start.defaults ⫽ { binary = "sequence" - , resources = { caps = 256, ram = Genode.units.MiB 16 } + , resources = { caps = 256, ram = Genode.units.MiB 10 } , routes = - [ Genode.ServiceRoute.parent "Timer" - , Genode.ServiceRoute.child "Block" "block" - , Genode.ServiceRoute.child "Nic" "nic" - ] + [ Genode.ServiceRoute.parent "Timer" + , Genode.ServiceRoute.child "Block" "block" + , Genode.ServiceRoute.child "Nic" "nic" + ] , config = Genode.Prelude.XML.text '' - - - - Hello_Solo5 - - - - - - - - - - '' + + + + Hello_Solo5 + + + + + + + + + + '' } } diff --git a/tests/solo5.nix b/tests/solo5.nix index 9a5115c..6372c57 100644 --- a/tests/solo5.nix +++ b/tests/solo5.nix @@ -7,13 +7,20 @@ rec { testConfig = lib.renderDhallInit ./solo5.dhall "{=}"; - testScript = '' - collect_modules ${solo5.tests}/bin/* - collect_modules ${solo5}/lib/solo5-bindings-genode/solo5.lib.so - collect_modules ${genode.os}/bin/nic_loopback - collect_modules ${genode.os}/bin/ram_block - collect_modules ${genode.os}/bin/sequence + bootModules = { + sequence = "${genode.os}/bin/sequence"; + solo5-test_blk = "${solo5.tests}/bin/solo5-test_blk"; + solo5-test_fpu = "${solo5.tests}/bin/solo5-test_fpu"; + solo5-test_globals = "${solo5.tests}/bin/solo5-test_globals"; + solo5-test_hello = "${solo5.tests}/bin/solo5-test_hello"; + solo5-test_quiet = "${solo5.tests}/bin/solo5-test_quiet"; + solo5-test_ssp = "${solo5.tests}/bin/solo5-test_ssp"; + "solo5.lib.so" = "${solo5}/lib/solo5-bindings-genode/solo5.lib.so"; + nic_loopback = "${genode.os}/bin/nic_loopback"; + ram_block = "${genode.os}/bin/ram_block"; + }; + testScript = '' run_genode_until "Error: stack protector check failed" 30 ''; }