better framework for running arm test

more explicit, rather than gobbling files, pass code in
preload is available (so code does not have to be duplicated)
interpret first, so bad mistakes get caught
no ssh, just qemu-arm, configure through env
This commit is contained in:
Torsten 2020-03-26 20:28:59 +02:00
parent 4bae5c418b
commit 94e4f3a9bf
2 changed files with 106 additions and 0 deletions

View File

@ -1,4 +1,79 @@
require_relative '../helper'
module Mains
module MainsHelper
include Preloader
include ScopeHelper
def setup
@qemu = ENV["qemu-arm"] || "qemu-arm"
@linker = ENV["arm-linux-gnu-ld"] || "arm-linux-gnu-ld" #on fedora
@arm = ENV["TEST_ARM"] or ENV["TEST_ALL"]
#@linker = "arm-linux-gnueabi-ld" # on ubuntu
# ENV["TEST_ARM"] = "DEBUG"
end
def assert_result( exit_code , stdout , name = nil)
name = caller_locations.first.label unless name
input = preload + @input
code , out = run_interpreter( input , name)
assert_equal exit_code , code , "interpreter code for #{name}"
assert_equal stdout , out , "interpreter stdout for #{name}"
return unless @arm
code , out = run_arm( input , name)
assert_equal exit_code , code , "arm code for #{name}"
assert_equal stdout , out , "arm stdout for #{name}"
end
# runnable_methods is called by minitest to determine which tests to run
def self.runnable_methods
all = Dir["test/mains/source/*_*.rb"]
tests =[]
return tests unless has_qemu
all.each do |file_name|
fullname = file_name.split("/").last.split(".").first
order , name , stdout , exit_code = fullname.split("_")
method_name = "test_#{order}_#{name}"
input = File.read(file_name)
tests << method_name
self.send(:define_method, method_name ) do
out , code = run_code(input , "#{order}_#{name}")
assert_equal stdout , out , "Wrong stdout #{name}"
assert_equal exit_code , code.to_s , "Wrong exit code #{name}"
end
end
tests
end
def run_arm(input , name )
puts "Compiling #{name}" if ENV["TEST_ARM"] == "DEBUG"
linker = ::RubyX::RubyXCompiler.new({}).ruby_to_binary( input , :arm )
writer = Elf::ObjectWriter.new(linker)
writer.save "mains.o"
puts "Linking #{name}" if ENV["TEST_ARM"] == "DEBUG"
`#{@linker} -N mains.o`
assert_equal 0 , $?.exitstatus , "Linking #{name} failed #{$?}"
puts "Running #{name}" if ENV["TEST_ARM"] == "DEBUG"
stdout = `#{@qemu} ./a.out`
exit_code = $?.exitstatus
puts "Arm #{stdout} #{exit_code}" if ENV["TEST_ARM"] == "DEBUG"
return exit_code , stdout
end
def run_interpreter(input , name )
puts "Interpreting #{name}" if ENV["TEST_ARM"] == "DEBUG"
compiler = RubyX::RubyXCompiler.new(RubyX.default_test_options)
linker = compiler.ruby_to_binary(input , :interpreter)
interpreter = Risc::Interpreter.new(linker)
interpreter.start_program
interpreter.tick while(interpreter.instruction)
saved_in = interpreter.std_reg(:saved_message)
assert_equal Parfait::Message , interpreter.get_register(saved_in).class
ret = interpreter.get_register(interpreter.std_reg(:syscall_1))
puts "Interpret #{interpreter.stdout} #{ret}" if ENV["TEST_ARM"] == "DEBUG"
return ret , interpreter.stdout
end
end
end

31
test/mains/test_assign.rb Normal file
View File

@ -0,0 +1,31 @@
require_relative "helper"
module Mains
class AssignTester < MiniTest::Test
include MainsHelper
def test_local
@input = as_main 'a = 15 ; return a'
assert_result 15 , ""
end
def test_plus
@preload = "Integer.plus"
@input = as_main("a = 5 + 5 ; return a")
assert_result 10 , ""
end
def test_plus2
@preload = "Integer.plus"
@input = as_main("a = 5 ;a = 5 + a ; return a")
assert_result 10 , ""
end
def test_plus3
@preload = "Integer.plus"
@input = as_main("a = 5 ;a = 5 + a ;a = a + 5; return a")
assert_result 15 , ""
end
end
end