Skip to content

Commit 4d6f79d

Browse files
author
Lillian Zhang
committed
Add Truffle specs for Thread.detect_recursion
1 parent d0bdb29 commit 4d6f79d

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved. This
2+
# code is released under a tri EPL/GPL/LGPL license. You can use it,
3+
# redistribute it and/or modify it under the terms of the:
4+
#
5+
# Eclipse Public License version 2.0, or
6+
# GNU General Public License version 2, or
7+
# GNU Lesser General Public License version 2.1.
8+
9+
require_relative '../../ruby/spec_helper'
10+
11+
describe "Thread#detect_recursion" do
12+
13+
before :each do
14+
def check_recursion_to_depth(obj, depth)
15+
return false unless obj.class.method_defined? :each
16+
Thread.detect_recursion obj do
17+
if depth > 1
18+
obj.each do |el|
19+
if check_recursion_to_depth(el, depth-1)
20+
return true
21+
end
22+
end
23+
end
24+
end
25+
end
26+
27+
def check_double_recursion_equality_to_depth(obj1, obj2, depth)
28+
# checks that obj1 and obj2 are both recursive and equal structurally
29+
# (because detect_recursion on two objects is only used during object comparison,
30+
# and aborts after inequality is discovered)
31+
return false unless obj1.class == obj2.class
32+
return false unless obj1.class.method_defined? :each
33+
return false unless obj1.size == obj2.size
34+
35+
Thread.detect_recursion obj1 obj2 do
36+
if depth > 1
37+
if obj1.class == Hash
38+
obj1.each do |key, val|
39+
return false unless obj2.has_key?(key)
40+
if check_double_recursion_equality_to_depth(val, obj2[key], depth-1)
41+
return true
42+
end
43+
end
44+
else
45+
obj1.size.times do |i|
46+
if check_double_recursion_equality_to_depth(obj1[i], obj2[i], depth-1)
47+
return true
48+
end
49+
end
50+
end
51+
end
52+
end
53+
end
54+
end
55+
56+
describe "for single arrays" do
57+
it "for non-recursive arrays returns false" do
58+
a = [1,[2,[3], 4],[[[5,6,7]]]]
59+
60+
10.times do |i|
61+
check_recursion_to_depth(a, i).should be_false
62+
end
63+
end
64+
it "for recursive arrays returns true after sufficient depth to detect recursion" do
65+
a = []
66+
a << [[[a]]]
67+
68+
b = []
69+
b << [1,[2,[3,b],4],5]
70+
71+
10.times do |i|
72+
if i < 5
73+
check_recursion_to_depth(a, i).should be_false
74+
check_recursion_to_depth(b, i).should be_false
75+
else
76+
check_recursion_to_depth(a, i).should be_true
77+
check_recursion_to_depth(b, i).should be_true
78+
end
79+
end
80+
end
81+
end
82+
83+
describe "for single hashes" do
84+
it "for non-recursive hashes returns false" do
85+
a = {:q => {:w => "qwe" }, :t => {:q => {:w => "qwe" }, :t => {:q => {:w => "qwe" }}}}
86+
87+
10.times do |i|
88+
check_recursion_to_depth(a, i).should be_false
89+
end
90+
end
91+
it "for recursive hashes returns true after sufficient depth to detect recursion" do
92+
a = {:q => {:w => "qwe" }}
93+
a[:t] = a
94+
95+
10.times do |i|
96+
if i < 3
97+
check_recursion_to_depth(a, i).should be_false
98+
else
99+
check_recursion_to_depth(a, i).should be_true
100+
end
101+
end
102+
end
103+
end
104+
105+
describe "for single structs" do
106+
it "for recursive structs returns true after sufficient depth to detect recursion" do
107+
car = Struct.new(:make, :model, :year)
108+
a = car.new("Honda", "Accord", "1998")
109+
a[:make] = a
110+
111+
10.times do |i|
112+
if i < 2
113+
check_recursion_to_depth(a, i).should be_false
114+
else
115+
check_recursion_to_depth(a, i).should be_true
116+
end
117+
end
118+
end
119+
end
120+
121+
describe "for single mixtures of types" do
122+
it "for recursive structs returns true after sufficient depth to detect recursion" do
123+
car = Struct.new(:make, :model, :year)
124+
a = car.new("Honda", "Accord", "1998")
125+
a[:make] = [{:car_make => ["a mess", {:here => a}]}]
126+
127+
10.times do |i|
128+
if i < 8
129+
check_recursion_to_depth(a, i).should be_false
130+
else
131+
check_recursion_to_depth(a, i).should be_true
132+
end
133+
end
134+
end
135+
end
136+
137+
describe "for a pair of arrays" do
138+
it "returns false when structure differs" do
139+
a = []
140+
a << a
141+
142+
c = [[[[[[[[[a,1]]]]]]]]]
143+
144+
10.times do |i|
145+
check_double_recursion_equality_to_depth(a, c, i).should be_false
146+
end
147+
end
148+
it "returns true after sufficient depth to detect recursion and equivalent structure" do
149+
a = []
150+
a << a
151+
152+
b = []
153+
b << [[[[[[b]]]]]]
154+
155+
10.times do |i|
156+
if i < 8
157+
check_double_recursion_equality_to_depth(a, b, i).should be_false
158+
else
159+
check_double_recursion_equality_to_depth(a, b, i).should be_true
160+
end
161+
end
162+
end
163+
end
164+
165+
describe "for a pair of hashes" do
166+
it "returns false when structure differs" do
167+
a = {:q => {:w => "qwe" }}
168+
a[:t] = a
169+
170+
b = {:q => {:w => "qwe" }, :t => {:t => {:w => "qwe" }, :q => a}}
171+
172+
10.times do |i|
173+
check_double_recursion_equality_to_depth(a, b, i).should be_false
174+
end
175+
end
176+
it "returns true after sufficient depth to detect recursion and equivalent structure" do
177+
a = {:q => {:w => "qwe" }}
178+
a[:t] = a
179+
180+
b = {:q => {:w => "qwe" }, :t => {:q => {:w => "qwe" }, :t => a}}
181+
182+
10.times do |i|
183+
if i < 4
184+
check_double_recursion_equality_to_depth(a, b, i).should be_false
185+
else
186+
check_double_recursion_equality_to_depth(a, b, i).should be_true
187+
end
188+
end
189+
end
190+
end
191+
192+
describe "for a pair of structs" do
193+
it "returns true after sufficient depth to detect recursion and equivalent structure" do
194+
car = Struct.new(:make, :model, :year)
195+
a = car.new("Honda", "Accord", "1998")
196+
a[:make] = a
197+
b = car.new(a, "Accord", "1998")
198+
199+
10.times do |i|
200+
if i < 3
201+
check_double_recursion_equality_to_depth(a, b, i).should be_false
202+
else
203+
check_double_recursion_equality_to_depth(a, b, i).should be_true
204+
end
205+
end
206+
end
207+
end
208+
209+
describe "for a pair of mixtures of types" do
210+
it "returns true after sufficient depth to detect recursion and equivalent structure" do
211+
car = Struct.new(:make, :model, :year)
212+
a = car.new("Honda", "Accord", "1998")
213+
a[:make] = [{:car_make => ["a mess", {:here => a}]}]
214+
b = car.new([{:car_make => ["a mess", {:here => a}]}], "Accord", "1998")
215+
216+
20.times do |i|
217+
if i < 11
218+
check_double_recursion_equality_to_depth(a, b, i).should be_false
219+
else
220+
check_double_recursion_equality_to_depth(a, b, i).should be_true
221+
end
222+
end
223+
end
224+
end
225+
end

0 commit comments

Comments
 (0)