unify fragment and parfait test code
so that we can test fragments remotely too
This commit is contained in:
parent
18f9ea019e
commit
7daaec6a0a
@ -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
|
||||
|
@ -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
|
||||
|
@ -17,7 +17,7 @@ class Object
|
||||
end
|
||||
HERE
|
||||
@length = 25
|
||||
check_return 4
|
||||
check 4
|
||||
end
|
||||
|
||||
def test_if_zero
|
||||
|
@ -29,6 +29,6 @@ class Object
|
||||
end
|
||||
HERE
|
||||
@length = 2525
|
||||
check_return 21
|
||||
check 21
|
||||
end
|
||||
end
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
88
test/soml/helper.rb
Normal 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
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user