ruby/yarvtest/test_flow.rb

592 строки
8.5 KiB
Ruby

#
# This test program is contributed by George Marrows
# Re: [Yarv-devel] Some tests for test_jump.rb
#
require 'yarvtest/yarvtest'
class TestFlow < YarvTestBase
def ae_flow(src, for_value=true)
# Tracks flow through the code
# A test like
# begin
# ensure
# end
# gets transformed into
# a = []
# begin
# begin; a << 1
# ensure; a << 2
# end; a << 3
# rescue Exception
# a << 99
# end
# a
# before being run. This tracks control flow through the code.
cnt = 0
src = src.gsub(/(\n|$)/) { "; $a << #{cnt+=1}\n" }
src = "$a = []; begin; #{src}; rescue Exception; $a << 99; end; $a"
if false#||true
STDERR.puts
STDERR.puts '#----'
STDERR.puts src
STDERR.puts '#----'
end
ae(src)
end
def test_while_with_ensure
ae %q{
a = []
i = 0
begin
while i < 1
i+=1
begin
begin
next
ensure
a << :ok
end
ensure
a << :ok2
end
end
ensure
a << :last
end
}
ae %q{
a = []
i = 0
begin
while i < 1
i+=1
begin
begin
break
ensure
a << :ok
end
ensure
a << :ok2
end
end
ensure
a << :last
end
}
ae %q{
a = []
i = 0
begin
while i < 1
if i>0
break
end
i+=1
begin
begin
redo
ensure
a << :ok
end
ensure
a << :ok2
end
end
ensure
a << :last
end
}
end
def test_ensure_normal_flow
ae_flow %{
begin
ensure
end }
end
def test_ensure_exception
ae_flow %{
begin
raise StandardError
ensure
end
}
end
def test_break_in_block_runs_ensure
ae_flow %{
[1,2].each do
begin
break
ensure
end
end
}
end
def test_next_in_block_runs_ensure
ae_flow %{
[1,2].each do
begin
next
ensure
end
end
}
end
def test_return_from_method_runs_ensure
ae_flow %{
o = "test"
def o.test(a)
return a
ensure
end
o.test(123)
}
end
def test_break_from_ifunc
ae %q{
["a"].inject("ng"){|x,y|
break :ok
}
}
ae %q{
unless ''.respond_to? :lines
class String
def lines
self
end
end
end
('a').lines.map{|e|
break :ok
}
}
ae_flow %q{
["a"].inject("ng"){|x,y|
break :ok
}
}
ae_flow %q{
('a'..'b').map{|e|
break :ok
}
}
end
def test_break_ensure_interaction1
# make sure that any 'break state' set up in the VM is c
# the time of the ensure
ae_flow %{
[1,2].each{
break
}
begin
ensure
end
}
end
def test_break_ensure_interaction2
# ditto, different arrangement
ae_flow %{
begin
[1,2].each do
break
end
ensure
end
}
end
def test_break_through_2_ensures
ae_flow %{
[1,2].each do
begin
begin
break
ensure
end
ensure
end
end
}
end
def test_ensure_break_ensure
# break through an ensure; run 2nd normally
ae_flow %{
begin
[1,2].each do
begin
break
ensure
end
end
ensure
end
}
end
def test_exception_overrides_break
ae_flow %{
[1,2].each do
begin
break
ensure
raise StandardError
end
end
}
end
def test_break_overrides_exception
ae_flow %{
[1,2].each do
begin
raise StandardError
ensure
break
end
end
}
ae_flow %{
[1,2].each do
begin
raise StandardError
rescue
break
end
end
}
end
def test_break_in_exception
ae_flow %q{
i=0
while i<3
i+=1
begin
ensure
break
end
end
}
ae_flow %q{
i=0
while i<3
i+=1
begin
raise
ensure
break
end
end
}
ae_flow %q{
i=0
while i<3
i+=1
begin
raise
rescue
break
end
end
}
end
def test_next_in_exception
return
ae_flow %q{
i=0
while i<3
i+=1
begin
ensure
next
end
end
}
ae_flow %q{
i=0
while i<3
i+=1
begin
raise
ensure
next
end
end
}
ae_flow %q{
i=0
while i<3
i+=1
begin
raise
rescue
next
end
end
}
end
def test_complex_break
ae_flow %q{
i = 0
while i<3
i+=1
j = 0
while j<3
j+=1
begin
raise
rescue
break
end
end
end
}
ae_flow %q{
i = 0
while i<3
i+=1
j = 0
while j<3
j+=1
1.times{
begin
raise
rescue
break
end
}
end
end
}
ae_flow %q{
i = 0
while i<3
i+=1
j = 0
while j<3
j+=1
begin
raise
ensure
break
end
end
end
}
ae_flow %q{
i = 0
while i<3
i+=1
j = 0
while j<3
j+=1
1.times{
begin
raise
ensure
break
end
}
end
end
}
ae_flow %q{
while true
begin
break
ensure
break
end
end
}
ae_flow %q{
while true
begin
break
ensure
raise
end
end
}
end
def test_jump_from_class
ae_flow %q{
3.times{
class C
break
end
}
}
ae_flow %q{
3.times{
class A
class B
break
end
end
}
}
ae_flow %q{
3.times{
class C
next
end
}
}
ae_flow %q{
3.times{
class C
class D
next
end
end
}
}
ae_flow %q{
while true
class C
break
end
end
}
ae_flow %q{
while true
class C
class D
break
end
end
end
}
ae_flow %q{
i=0
while i<3
i+=1
class C
next 10
end
end
}
ae %q{
1.times{
while true
class C
begin
break
ensure
break
end
end
end
}
}
end
def test_flow_with_cont_sp
ae %q{
def m a, b
a + b
end
m(1,
while true
break 2
end
)
}
ae %q{
def m a, b
a + b
end
m(1,
(i=0; while i<2
i+=1
class C
next 2
end
end; 3)
)
}
ae %q{
def m a, b
a+b
end
m(1, 1.times{break 3}) +
m(10, (1.times{next 3}; 20))
}
end
def test_return_in_deep_stack
ae_flow %q{
def m1 *args
end
def m2
m1(:a, :b, (return 1; :c))
end
m2
}
end
def test_return_in_ensure
ae_flow %q{
def m()
begin
2
ensure
return 3
end
end
m
}
ae_flow %q{
def m2
end
def m()
m2(begin
2
ensure
return 3
end)
4
end
m()
}
ae_flow %q{
def m
1
1.times{
2
begin
3
return
4
ensure
5
end
6
}
7
end
m()
}
end
end