mirror of
https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials.git
synced 2024-11-03 15:40:21 +00:00
144 lines
3.7 KiB
Ruby
Executable File
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
|