require_relative '../helper' module Mains module MainsHelper include Preloader include ScopeHelper def setup @qemu = ENV["QEMU_ARM"] || "qemu-arm" @linker = ENV["ARM_LINKER"] || "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