rust-raspberrypi-OS-tutorials/13_integrated_testing/tests/runner.rb
2021-01-01 11:28:32 +01:00

144 lines
3.7 KiB
Ruby
Executable File

#!/usr/bin/env ruby
# frozen_string_literal: true
# SPDX-License-Identifier: MIT OR Apache-2.0
#
# Copyright (c) 2019-2021 Andre Richter <andre.o.richter@gmail.com>
require 'English'
require 'pty'
# Test base class.
class Test
INDENT = ' '
def print_border(status)
puts
puts "#{INDENT}-------------------------------------------------------------------"
puts status
puts "#{INDENT}-------------------------------------------------------------------\n\n\n"
end
def print_error(error)
puts
print_border("#{INDENT}❌ Failure: #{error}: #{@test_name}")
end
def print_success
print_border("#{INDENT}✅ Success: #{@test_name}")
end
def print_output
puts "#{INDENT}-------------------------------------------------------------------"
print INDENT
print '🦀 '
print @output.join.gsub("\n", "\n#{INDENT}")
end
def finish(error)
print_output
exit_code = if error
print_error(error)
false
else
print_success
true
end
exit(exit_code)
end
end
# Executes tests with console I/O.
class ConsoleTest < Test
def initialize(binary, qemu_cmd, test_name, console_subtests)
super()
@binary = binary
@qemu_cmd = qemu_cmd
@test_name = test_name
@console_subtests = console_subtests
@cur_subtest = 1
@output = ["Running #{@console_subtests.length} console-based tests\n",
"-------------------------------------------------------------------\n\n"]
end
def format_test_name(number, name)
formatted_name = "#{number.to_s.rjust(3)}. #{name}"
formatted_name.ljust(63, '.')
end
def run_subtest(subtest, qemu_out, qemu_in)
@output << format_test_name(@cur_subtest, subtest.name)
subtest.run(qemu_out, qemu_in)
@output << "[ok]\n"
@cur_subtest += 1
end
def exec
error = false
PTY.spawn(@qemu_cmd) do |qemu_out, qemu_in|
begin
@console_subtests.each { |t| run_subtest(t, qemu_out, qemu_in) }
rescue StandardError => e
error = e.message
end
finish(error)
end
end
end
# A wrapper around the bare QEMU invocation.
class RawTest < Test
MAX_WAIT_SECS = 5
def initialize(binary, qemu_cmd, test_name)
super()
@binary = binary
@qemu_cmd = qemu_cmd
@test_name = test_name
@output = []
end
def exec
error = 'Timed out waiting for test'
io = IO.popen(@qemu_cmd)
while IO.select([io], nil, nil, MAX_WAIT_SECS)
begin
@output << io.read_nonblock(1024)
rescue EOFError
io.close
error = $CHILD_STATUS.to_i != 0
break
end
end
finish(error)
end
end
##--------------------------------------------------------------------------------------------------
## Script entry point
##--------------------------------------------------------------------------------------------------
binary = ARGV.last
test_name = binary.gsub(%r{.*deps/}, '').split('-')[0]
console_test_file = "tests/#{test_name}.rb"
qemu_cmd = ARGV.join(' ')
test_runner = if File.exist?(console_test_file)
load console_test_file
# subtest_collection is provided by console_test_file
ConsoleTest.new(binary, qemu_cmd, test_name, subtest_collection)
else
RawTest.new(binary, qemu_cmd, test_name)
end
test_runner.exec