unify fragment and parfait test code

so that we can test fragments remotely too
This commit is contained in:
Torsten Ruger 2015-11-18 13:04:57 +02:00
parent 18f9ea019e
commit 7daaec6a0a
12 changed files with 160 additions and 152 deletions

View File

@ -1,36 +1,20 @@
require_relative '../../helper'
require "register/interpreter"
require_relative '../helper'
# Fragments are small programs that we run through the interpreter and really only check
# - the no. of instructions processed
# - the stdout output
module Fragments
include RuntimeTests
# define setup to NOT load parfait.
def setup
@stdout = ""
end
def check
machine = Register.machine.boot
machine.parse_and_compile @string_input
machine.collect
@interpreter = Register::Interpreter.new
@interpreter.start machine.init
count = 0
begin
count += 1
#puts interpreter.instruction
@interpreter.tick
end while( ! @interpreter.instruction.nil?)
assert_equal @length , count
assert_equal @stdout , @interpreter.stdout
@machine = Register.machine.boot
end
def check_return val
check
assert_equal Parfait::Message , @interpreter.get_register(:r0).class
assert_equal val , @interpreter.get_register(:r0).return_value
def main()
@string_input
end
end

View File

@ -30,7 +30,7 @@ class Object
end
HERE
@length = 505
check_return 80
check 80
end
def test_class_method
@ -47,7 +47,7 @@ class Object
end
HERE
@length = 33
check_return 5
check 5
end
def test_class_method_fails

View File

@ -17,7 +17,7 @@ class Object
end
HERE
@length = 25
check_return 4
check 4
end
def test_if_zero

View File

@ -29,6 +29,6 @@ class Object
end
HERE
@length = 2525
check_return 21
check 21
end
end

View File

@ -12,7 +12,7 @@ class Object
end
HERE
@length = 15
check_return 5
check 5
end
def test_return2
@ -28,7 +28,7 @@ class Object
end
HERE
@length = 35
check_return 5
check 5
end
def test_return3
@ -45,7 +45,7 @@ class Object
end
HERE
@length = 39
check_return 5
check 5
end
end

View File

@ -31,14 +31,14 @@ HERE
fibo 48
@length = 1241
# this is not the correct fibo, just what comes from wrapping (smaller than below)
check_return 512559680
check 512559680
end
# highest 32 bit fibo
def test_while_fibo47
fibo 47
@length = 1216
check_return 2971215073
check 2971215073
end
end

View File

@ -1,5 +1,6 @@
require_relative 'helper'
module Soml
class TestWord < MiniTest::Test
include Fragments
@ -21,3 +22,4 @@ HERE
check
end
end
end

88
test/soml/helper.rb Normal file
View File

@ -0,0 +1,88 @@
require_relative '../helper'
require "register/interpreter"
require "rye"
Rye::Cmd.add_command :ld, '/usr/bin/ld'
Rye::Cmd.add_command :aout, './a.out'
# machinery to run a soml program in 2 ways
# - first by running it through the interpreter
# - second by assembling to arm , pushing the binary to a remote machine and executing it there
#
# The second obviously takes a fair bit of time so it's only done when an REMOTE is set
# REMOTE has to be set to user@machine:port or it will default to an emulator
module RuntimeTests
def setup
@stdout = ""
@machine = Register.machine.boot
Soml::Compiler.load_parfait
end
def check ret = nil
@machine.parse_and_compile main()
@machine.collect
@interpreter = Register::Interpreter.new
@interpreter.start @machine.init
count = 0
begin
count += 1
#puts interpreter.instruction
@interpreter.tick
end while( ! @interpreter.instruction.nil?)
assert_equal @stdout , @interpreter.stdout , "stdout wrong locally"
if ret
assert_equal Parfait::Message , @interpreter.get_register(:r0).class
assert_equal ret , @interpreter.get_register(:r0).return_value , "exit wrong #{@string_input}"
end
check_remote ret
file = write_object_file
end
def connected
return false unless ENV["REMOTE"]
user , rest = ENV["REMOTE"].split("@")
machine , port = rest.split(":")
return @@conn if defined?(@@conn)
@@conn = Rye::Box.new(machine | "localhost" , :port => (port | 2222) , :user => (user | "pi"))
end
def check_remote ret
return unless box = connected
return unless ret.is_a?(Numeric)
file = write_object_file
r_file = file.sub("./" , "salama/")
box.file_upload file , r_file
box.ld "-N", r_file
begin #need to rescue here as rye throws if no return 0
ret = box.aout # and we use return to mean something
rescue Rye::Err => e # so it's basically never 0
ret = e.rap
end
assert_equal @stdout , ret.stdout.join , "remote std was #{ret.stdout}" if @stdout
assert_equal "" , ret.stderr.join , "remote had error"
if ret
should = @interpreter.get_register(:r0).return_value
assert_equal should , ret.exit_status.to_i , "remote exit failed for #{@string_input}"
end
end
def write_object_file
file_name = caller(3).first.split("in ").last.chop.sub("`","")
return if file_name.include?("run")
file_name = "./tmp/" + file_name + ".o"
Register.machine.translate_arm
writer = Elf::ObjectWriter.new
writer.save file_name
file_name
end
def check_return val
check val
end
def check_return_class val
check
assert_equal val , @interpreter.get_register(:r0).return_value.class
end
end

View File

@ -1,94 +1,28 @@
require_relative '../../helper'
require "register/interpreter"
require "rye"
Rye::Cmd.add_command :ld, '/usr/bin/ld'
Rye::Cmd.add_command :aout, './a.out'
require_relative '../helper'
module RuntimeTests
# Parfait test test just that, parfait.
#
# The idea is to have really really small main programs that test one very small thing
# AND return an exit code (or write stdout) that can be checked by
# compiling and running the thing remotely
#
module ParfaitTests
include RuntimeTests
def setup
@stdout = ""
@machine = Register.machine.boot
Soml::Compiler.load_parfait
end
def main
<<HERE
runko = <<HERE
class Object
int main()
PROGRAM
end
end
HERE
end
def check ret = nil
machine = Register.machine.boot
Soml::Compiler.load_parfait
machine.parse_and_compile main.sub("PROGRAM" , @string_input )
machine.collect
@interpreter = Register::Interpreter.new
@interpreter.start machine.init
count = 0
begin
count += 1
#puts interpreter.instruction
@interpreter.tick
end while( ! @interpreter.instruction.nil?)
assert_equal @stdout , @interpreter.stdout , "stdout wrong locally"
if ret
assert_equal Parfait::Message , @interpreter.get_register(:r0).class
assert_equal ret , @interpreter.get_register(:r0).return_value , "exit wrong #{@string_input}"
end
check_remote ret
file = write_object_file
end
def connected
return @@conn if defined?(@@conn)
return @@conn = false
begin
box = Rye::Box.new("localhost" , :port => 2222 , :user => "pi")
box.pwd
puts "connected, testing also remotely"
@@conn = box
rescue Rye::Err
@@conn = false
end
return @@conn
end
def check_remote ret
return unless box = connected
return unless ret.is_a?(Numeric)
file = write_object_file
r_file = file.sub("./" , "salama/")
box.file_upload file , r_file
box.ld "-N", r_file
begin #need to rescue here as rye throws if no return 0
ret = box.aout # and we use return to mean something
rescue Rye::Err => e # so it's basically never 0
ret = e.rap
end
assert_equal @stdout , ret.stdout.join , "remote std was #{ret.stdout}" if @stdout
assert_equal "" , ret.stderr.join , "remote had error"
if ret
should = @interpreter.get_register(:r0).return_value
assert_equal should , ret.exit_status.to_i , "remote exit failed for #{@string_input}"
end
end
def write_object_file
file_name = caller(3).first.split("in ").last.chop.sub("`","")
return if file_name.include?("run")
file_name = "./tmp/" + file_name + ".o"
Register.machine.translate_arm
writer = Elf::ObjectWriter.new
writer.save file_name
file_name
end
def check_return val
check val
end
def check_return_class val
check
assert_equal val , @interpreter.get_register(:r0).return_value.class
runko.sub("PROGRAM" , @main )
end
end

View File

@ -1,30 +1,30 @@
require_relative 'helper'
class TestPutiRT < MiniTest::Test
include RuntimeTests
include ParfaitTests
def test_mod4_2
@string_input = "return 2.mod4()"
@main = "return 2.mod4()"
check_return 2 % 4
end
def test_mod4_3
@string_input = "return 3.mod4()"
@main = "return 3.mod4()"
check_return 3 % 4
end
def test_mod4_4
@string_input = "return 4.mod4()"
@main = "return 4.mod4()"
check_return 4 % 4
end
def test_mod4_5
@string_input = "return 5.mod4()"
@main = "return 5.mod4()"
check_return 5 % 4
end
def test_mod4_12
@string_input = "return 12.mod4()"
@main = "return 12.mod4()"
check_return 12 % 4
end
def test_mod4_10
@string_input = "return 10.mod4()"
@main = "return 10.mod4()"
check_return 10 % 4
end
@ -45,31 +45,31 @@ class TestPutiRT < MiniTest::Test
end
def test_hightimes2
@string_input = "return 2.high_times(12 , 333)"
@main = "return 2.high_times(12 , 333)"
check_return high_times(2,12,333)
end
def test_hightimes3456
@string_input = "return 3456.high_times(12 , 333)"
@main = "return 3456.high_times(12 , 333)"
check_return high_times(3456,12,333)
end
def test_hightimes234567
@string_input = "return 234567.high_times(12 , 333)"
@main = "return 234567.high_times(12 , 333)"
check_return high_times(234567,12,333)
end
def test_hightimes
@string_input = "return 234567.high_times(12 , 333)"
@main = "return 234567.high_times(12 , 333)"
check_return high_times(234567,12,333)
end
def test_lowtimes2
@string_input = "return 2.low_times(14 , 33)"
@main = "return 2.low_times(14 , 33)"
check_return low_times(2,14,33)
end
def test_lowtimes3456
@string_input = "return 3456.low_times(14 , 33)"
@main = "return 3456.low_times(14 , 33)"
check_return low_times(3456,14,33)
end
def test_lowtimes234567
@string_input = "return 234567.low_times(14 , 33)"
@main = "return 234567.low_times(14 , 33)"
check_return low_times(234567,14,33)
end
@ -78,75 +78,75 @@ class TestPutiRT < MiniTest::Test
# (off course the bug is not included in the test, but easy to achieve with random numbers )
# for high numbers with ending 0 they are all 1 low. Possibly Interpreter bug ?
def test_div10_2
@string_input = "return 2.div10()"
@main = "return 2.div10()"
check_return 2 / 10
end
def test_div10_10
@string_input = "return 10.div10()"
@main = "return 10.div10()"
check_return 10 / 10
end
def test_div10_12345
@string_input = "return 12345.div10()"
@main = "return 12345.div10()"
check_return 12345 / 10
end
def test_div10_234567
@string_input = "return 234567.div10()"
@main = "return 234567.div10()"
check_return 234567 / 10
end
def test_as_char1
@string_input = "return 5.as_char()"
@main = "return 5.as_char()"
check_return 53
end
def test_as_char2
@string_input = "return 10.as_char()"
@main = "return 10.as_char()"
check_return 32
end
def test_tos_one_digit
@string_input = "Word five = 5.to_s()
@main = "Word five = 5.to_s()
five.putstring()"
@stdout = " 5"
check
end
def test_tos_zero
@string_input = "Word five = 0.to_s()
@main = "Word five = 0.to_s()
five.putstring()"
@stdout = " 0"
check
end
def test_tos_two_digit
@string_input = "Word five = 15.to_s()
@main = "Word five = 15.to_s()
five.putstring()"
@stdout = " 15"
check
end
def test_tos_three_digit
@string_input = "Word five = 150.to_s()
@main = "Word five = 150.to_s()
five.putstring()"
@stdout = " 150"
check
end
def test_puti_four_digit
@string_input = "return 1234.puti()"
@main = "return 1234.puti()"
@stdout = " 1234"
check_return 1234
end
def test_puti_seven_digit
@string_input = "int i = 301 * 4096
@main = "int i = 301 * 4096
i = i + 1671
return i.puti()"
@stdout = " 1234567"
check_return 1234567
end
def test_puti_eight_digit
@string_input = "int i = 3014 * 4096
@main = "int i = 3014 * 4096
i = i + 334
return i.puti()"
@stdout = " 12345678"

View File

@ -1,26 +1,26 @@
require_relative 'helper'
class TestLayoutRT < MiniTest::Test
include RuntimeTests
include ParfaitTests
def test_main
@string_input = "return 1"
@main = "return 1"
check_return 1
end
def test_get_layout
@string_input = "return get_layout()"
@main = "return get_layout()"
check_return_class Parfait::Layout
end
def test_get_class
@string_input = "return get_class()"
@main = "return get_class()"
check_return_class Parfait::Class
end
def test_puts_class
@string_input = <<HERE
@main = <<HERE
Class c = get_class()
Word w = c.get_name()
w.putstring()

View File

@ -1,10 +1,10 @@
require_relative 'helper'
class TestwordRT < MiniTest::Test
include RuntimeTests
include ParfaitTests
def test_len
@string_input = <<HERE
@main = <<HERE
Word w = " "
return w.char_length
HERE
@ -12,7 +12,7 @@ HERE
end
def test_space
@string_input = <<HERE
@main = <<HERE
Word w = " "
return w.char_at(1)
HERE
@ -21,7 +21,7 @@ HERE
end
def test_add_doesnt_change1
@string_input = <<HERE
@main = <<HERE
Word w = " "
w.push_char(48)
return w.char_at(1)
@ -29,7 +29,7 @@ HERE
check_return 32
end
def test_after_add_get_works
@string_input = <<HERE
@main = <<HERE
Word w = " "
w.push_char(48)
return w.char_at(2)
@ -38,7 +38,7 @@ HERE
end
def test_after_add_length_works
@string_input = <<HERE
@main = <<HERE
Word w = " "
w.push_char(32)
return w.char_length
@ -47,7 +47,7 @@ HERE
end
def test_get1
@string_input = <<HERE
@main = <<HERE
Word w = "12345"
return w.char_at(1)
HERE
@ -55,7 +55,7 @@ HERE
end
def test_get2
@string_input = <<HERE
@main = <<HERE
Word w = "12345"
return w.char_at(2)
HERE