#################### ## User interface ## #################### # # Convenience variables for debugging one specific test # # single_test_pkg: if set to one of the test packages, only this one is run # single_test_build: list of components that shall be build from repos # single_test_modules: list of boot modules to overlay the test-depot content # # To get a hint which build components and which boot modules you may want to # enter for a given test package please see these files: # # repos//recipes/pkg//archives # repos//recipes/pkg//runtime ( tag) # # Example: # # set single_test_pkg "test-libc_vfs" # set single_test_build { server/ram_fs test/libc_vfs } # set single_test_modules { ram_fs test-libc_vfs vfs.lib.so } # set single_test_pkg "" set single_test_build { } set single_test_modules { } # # The list of available test packages - was obtained by issuing: # # ! cd /repos # ! find . -type d -wholename *recipes/pkg/test-* -printf '%f\n' | sort # set avail_test_pkgs { test-ada test-ada_exception test-ada_secondary_stack test-blk test-blk_cache test-clipboard test-ds_ownership test-dynamic_config test-dynamic_config_loader test-dynamic_config_slave test-expat test-fault_detection test-fs_log test-fs_packet test-fs_report test-fs_rom_update test-fs_rom_update_fs test-fs_rom_update_ram test-init test-init_loop test-ldso test-libc test-libc_counter test-libc_getenv test-libc_pipe test-libc_vfs test-libc_vfs_audit test-libc_vfs_block test-libc_vfs_counter test-libc_vfs_fs test-libc_vfs_fs_chained test-libc_vfs_ram test-log test-lx_block test-magic_ring_buffer test-mmio test-new_delete test-nic_loopback test-part_blk_gpt test-part_blk_mbr test-pipe test-pthread test-python test-ram_fs_chunk test-read_only_rom test-reconstructible test-registry test-report_rom test-resource_request test-resource_yield test-rm_fault test-rm_fault_no_nox test-rm_nested test-rom_blk test-rom_filter test-rust test-sequence test-signal test-slab test-solo5 test-stdcxx test-synced_interface test-tcp_bulk_lwip test-tcp_bulk_lxip test-terminal_crosslink test-timed_semaphore test-timer test-trace test-trace_logger test-utf8 test-vfs_stress_fs test-vfs_stress_ram test-weak_ptr test-xml_generator test-xml_node gcov } set avail_test_src_pkgs { test-xml_generator } if { $single_test_pkg != "" && [lsearch -exact $avail_test_pkgs $single_test_pkg] == -1} { puts stderr "Error: single_test_pkg \"$single_test_pkg\" not available" exit 1 } # # Whether the platform supports non-executable dataspaces # proc non_executable_supported { } { if {[have_spec hw] && [have_spec x86_64]} { return true } if {[have_spec hw] && [have_spec arm]} { return true } if {[have_spec nova] && [have_spec x86_64]} { return true } if {[have_spec foc] && [have_spec x86_64]} { return true } if {[have_spec foc] && [have_spec arm]} { return true } if {[have_spec sel4] && [have_spec arm]} { return true } return false } # # Whether to skip a test - if undefined for a test, the test is not skipped # set skip_test_pkg(test-python) [expr ![have_spec x86]] set skip_test_pkg(test-slab) [expr [get_cmd_switch --autopilot] && [have_include "power_on/qemu"]] set skip_test_pkg(test-rm_nested) [expr [have_spec linux]] set skip_test_pkg(test-fault_detection) [expr [have_spec pistachio] || [have_spec fiasco]] set skip_test_pkg(test-fs_packet) [expr [get_cmd_switch --autopilot] && [have_include "power_on/qemu"]] set skip_test_pkg(test-rm_fault) [expr [have_spec linux] || ![non_executable_supported]] set skip_test_pkg(test-rm_fault_no_nox) [expr [have_spec linux] || !$skip_test_pkg(test-rm_fault)] set skip_test_pkg(test-lx_block) [expr ![have_spec linux]] set skip_test_pkg(test-tcp_bulk_lwip) [expr ![have_spec x86]] set skip_test_pkg(test-tcp_bulk_lxip) [expr ![have_spec x86]] set skip_test_pkg(test-solo5) [expr ![have_spec x86_64]] # # FIXME # # When doing the libc_getenv test on autopilot+foc+x86 and one of the # subsequent tests crashes the system so it gets rebooted by the run script, # the system doesn't come up again. It gets stuck after core initialization. # set skip_test_pkg(test-libc_getenv) [expr [get_cmd_switch --autopilot] && [have_spec foc] && [have_spec x86]] ############################################################## ## Local copies of run tool procedures with small adaptions ## ## ## ## FIXME: Adapt original and remove local copies ## ############################################################## proc autopilot_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 } set platform_msg [run_boot_string] if {$platform_msg eq ""} { set platform_msg "undefined platform command startup string sequence" } expect { -i $running_spawn_id $platform_msg { puts stderr "Error: platform rebooted unexpectedly"; exit -4 } -i $running_spawn_id -re $wait_for_re { } eof { puts stderr "Error: Spawned process died unexpectedly"; exit -3 } timeout { puts stderr "Error: Test execution timed out"; global last_test_timed_out set last_test_timed_out 1 return } } append output $expect_out(buffer) } proc autopilot_create_tar_from_depot_binaries { archive_path args } { # filter out api and src archives from requested depot content set content {} foreach subdir [_collect_from_depot $args] { if {[regexp [_depot_archive_versioned_path_pattern] $subdir dummy user type]} { if {$type == "src"} continue; if {$type == "api"} continue; } lappend content $subdir } check_for_missing_depot_archives eval "exec tar cf $archive_path -T /dev/null -C [depot_dir] [lsort -unique $content]" } proc autopilot_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} { autopilot_wait_for_output $wait_for_re $timeout_value $running_spawn_id return; } set retry 3 while { $retry != 0 } { if {[expr [run_power_on] == false]} { puts "Power on step failed, retry." sleep 3 incr retry -1; continue } if {![run_load]} { puts "Load step failed, retry." # kill the spawned load process if there is one if {[load_spawn_id] != -1} { set pid [exp_pid -i [load_spawn_id]] exec kill -9 $pid } incr retry -1; continue; } if {![run_log $wait_for_re $timeout_value]} { puts "Log step failed, retry." incr retry -1; continue; } return; } puts stderr "Boot process failed 3 times in series. I give up!"; exit -1; } ######################## ## Utility procedures ## ######################## proc depot_user {} { return [get_cmd_arg --depot-user genodelabs] } # # Check if archives are available without doing anything with them # proc check_archives_available { args } { # filter out api and src archives from requested depot content set content {} foreach subdir [_collect_from_depot $args] { if {[regexp [_depot_archive_versioned_path_pattern] $subdir dummy user type]} { if {$type == "src"} continue; if {$type == "api"} continue; } lappend content $subdir } check_for_missing_depot_archives } # # Return routes for boot modules that shall overlay the test-depot content # proc single_test_module_routes { } { global single_test_modules set result "" foreach module $single_test_modules { append result { } } return $result } # # Return autopilot start-nodes for the test packages that shall be run # proc test_pkgs_start_nodes { } { global test_pkgs global skip_test_pkg set result "" foreach test_pkg $test_pkgs { if { [info exists skip_test_pkg($test_pkg)] && $skip_test_pkg($test_pkg)} { append result { } } else { append result { } } } return $result } # # Prepare to call run_genode_until (again, with a changed setup) # proc prepare_to_run_genode { } { global output global qemu_args global previous_results global previous_time_ms global previous_succeeded global previous_failed global previous_skipped global skip_test_pkg global test_pkgs global test_src_pkgs global single_test_build global single_test_modules global last_test_pkg global last_test_timed_out global serial_id global timeout set qemu_args " -nographic -serial mon:stdio" # # Create a depot archive that contains the test packages # create_boot_directory set depot_tar_archives "" set depot_tar_src_archives "" set import_archives "" foreach test_pkg $test_pkgs { if { [info exists skip_test_pkg($test_pkg)] } { append_if [expr !$skip_test_pkg($test_pkg)] depot_tar_archives " [depot_user]/pkg/$test_pkg " } else { append depot_tar_archives " [depot_user]/pkg/$test_pkg " } } foreach test_src_pkg $test_src_pkgs { if { [info exists skip_test_pkg($test_src_pkg)] } { append_if [expr !$skip_test_pkg($test_src_pkg)] depot_tar_src_archives " [depot_user]/src/$test_src_pkg " } else { append depot_tar_src_archives " [depot_user]/src/$test_src_pkg " } } append import_archives { } [depot_user] {/src/} [base_src] { } [depot_user] {/src/report_rom } [depot_user] {/src/fs_rom } [depot_user] {/src/vfs } [depot_user] {/src/loader } [depot_user] {/src/init } [depot_user] {/src/depot_query } if {!$skip_test_pkg(test-lx_block)} { append import_archives [depot_user] {/raw/test-lx_block } } set all_archives [concat $depot_tar_archives $import_archives] check_archives_available {*}$all_archives autopilot_create_tar_from_depot_binaries [run_dir]/genode/depot.tar {*}$depot_tar_archives set depot_tar_wo_src_size [file size [run_dir]/genode/depot.tar] append_src_and_api_depot_packages_to_tar [run_dir]/genode/depot.tar {*}$depot_tar_src_archives set depot_tar_size [file size [run_dir]/genode/depot.tar] puts "Depot archive has a size of $depot_tar_size bytes ($depot_tar_wo_src_size bytes without sources)" # # Install the root-init config # append config { } [single_test_module_routes] { } $previous_results { } [test_pkgs_start_nodes] { } [single_test_module_routes] { } install_config $config # # Create the rest of the boot modules # set build_components { app/depot_autopilot } append build_components $single_test_build build $build_components import_from_depot {*}$import_archives # # Build boot image from boot modules # set boot_modules { depot_autopilot } append boot_modules $single_test_modules build_boot_image $boot_modules set last_test_pkg "" set last_test_timed_out 0 set serial_id -1 set timeout 20 } ################## ## Main routine ## ################## # # Check platform support # if {[expr ![have_spec x86] && \ ![have_spec arm_v7a] ]} \ { puts "\n Run script is not supported on this platform. \n"; exit 0 } # # Compose the test_pkgs list from a list of available test packages by # applying the single_test_pkg variable. # set test_pkgs "" foreach test_pkg $avail_test_pkgs { if { $single_test_pkg == "" || $single_test_pkg == $test_pkg } { append test_pkgs " $test_pkg " } } # # Compose the test_src_pkgs list from a list of available source packages by # applying the single_test_pkg variable. # set test_src_pkgs "" foreach test_src_pkg $avail_test_src_pkgs { if { $single_test_pkg == "" || $single_test_pkg == $test_src_pkg } { append test_src_pkgs " $test_src_pkg " } } set previous_results "" set previous_time_ms 0 set previous_succeeded 0 set previous_failed 0 set previous_skipped 0 prepare_to_run_genode while {1} { # wait for the next autopilot event if {$serial_id == -1} { run_genode_until {depot_autopilot\] --- .*?\n} $timeout } else { set init_time_ms [clock clicks -millisec] autopilot_run_genode_until {depot_autopilot\] --- .*?\n} $timeout $serial_id set previous_time_ms [expr $previous_time_ms + [expr ([clock clicks -millisec] - $init_time_ms)] ] } # remove last test from list and check if we have to reboot the system set serial_id [output_spawn_id] if {$last_test_pkg != ""} { set test_pkgs [lsearch -all -inline -not -exact $test_pkgs $last_test_pkg] if {$last_test_timed_out} { # shut-down running system exec kill -9 [exp_pid -i $serial_id] run_power_off # remember result of last test if {$previous_results != ""} { append previous_results \012 } append previous_results { } [format {%-31s %-6s %7s} $last_test_pkg "failed " "$timeout.000"] { reboot} incr previous_failed # prepare system re-boot prepare_to_run_genode continue } } # if the autopilot finished all tests, evaluate its return value if {[regexp {depot_autopilot\] --- Finished} $output]} { set output "" run_genode_until {child "depot_autopilot" exited with exit value.*?\n} 10 $serial_id grep_output {^\[init\] } compare_output_to {[init] child "depot_autopilot" exited with exit value 0} exit 0 } # if the autopilot started a new test, set a new timeout if {[regexp {depot_autopilot\] --- Run} $output]} { if {$last_test_pkg != ""} { # remember result of last test in case the system must be restartet set last_test_result "" regexp {depot_autopilot\] ( [^\033]+)} $output ignored last_test_result regsub -all {<} $last_test_result {\<} last_test_result set failed_off [string first " failed" $last_test_result] set skipped_off [string first " skipped" $last_test_result] set ok_off [string first " ok" $last_test_result] if {$failed_off > 0 && ($skipped_off < 0 || $failed_off < $skipped_off) && ($ok_off < 0 || $failed_off < $ok_off)} { incr previous_failed } elseif {$skipped_off > 0 && ($ok_off < 0 || $skipped_off < $ok_off)} { incr previous_skipped } elseif {$ok_off > 0} { incr previous_succeeded } else { puts "Error: malformed test result" puts $last_test_result exit -1 } if {$previous_results != ""} { append previous_results \012 } append previous_results $last_test_result } # determine timeout for the next timeout set min_timeout 10 regexp {depot_autopilot\] --- Run "(.*?)" \(max ([0-9]*?) } $output] ignore last_test_pkg min_timeout set timeout [expr $min_timeout + 10] set output "" } }