cast 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,174 @@
1
+ $: << File.expand_path('../lib')
2
+ require 'cast'
3
+ require 'test/unit'
4
+
5
+ if true
6
+ class C::Node
7
+ def pretty_print q
8
+ q.text self.to_debug
9
+ end
10
+ end
11
+ end
12
+
13
+ class Array
14
+ def same_list? other
15
+ self.length == other.length or
16
+ return false
17
+ self.zip(other).all? do |mine, yours|
18
+ mine.equal? yours or
19
+ return false
20
+ end
21
+ end
22
+ end
23
+
24
+ class Integer
25
+ ###
26
+ ### Return a `self'-element array containing the result of the given
27
+ ### block.
28
+ ###
29
+ def of &blk
30
+ Array.new(self, &blk)
31
+ end
32
+ end
33
+
34
+ module Test::Unit::Assertions
35
+ ###
36
+ ### Assert that the given ast's nodes' parents are correct, and
37
+ ### there aren't non-Nodes where there shouldn't be.
38
+ ###
39
+ def assert_tree ast
40
+ meth = 'unknown method'
41
+ caller.each do |line|
42
+ if line =~ /in `(test_.*?)'/ #`
43
+ meth = $1
44
+ break
45
+ end
46
+ end
47
+ filename = "#{self.class}_#{meth}.out"
48
+ begin
49
+ assert_tree1(ast, nil)
50
+ assert(true)
51
+ rescue BadTreeError => e
52
+ require 'pp'
53
+ open("#{filename}", 'w'){|f| PP.pp(ast, f)}
54
+ flunk("#{e.message}. Output dumped to `#{filename}'.")
55
+ end
56
+ end
57
+ ###
58
+ def assert_tree1 x, parent
59
+ if x.is_a? C::Node
60
+ parent.equal? x.parent or
61
+ raise BadTreeError, "#{x.class}:0x#{(x.id << 1).to_s(16)} has #{x.parent ? 'wrong' : 'no'} parent"
62
+ x.fields.each do |field|
63
+ next if !field.child?
64
+ val = x.send(field.reader)
65
+ next if val.nil?
66
+ val.is_a? C::Node or
67
+ raise BadTreeError, "#{x.class}:0x#{(x.id << 1).to_s(16)} is a non-Node child"
68
+ assert_tree1(val, x)
69
+ end
70
+ end
71
+ end
72
+ class BadTreeError < StandardError; end
73
+ ###
74
+ ### Assert that `arg' is a C::NodeList.
75
+ ###
76
+ def assert_list arg
77
+ assert_kind_of(C::NodeList, arg)
78
+ end
79
+ ###
80
+ ### Assert that `arg' is an empty C::NodeList.
81
+ ###
82
+ def assert_empty_list arg
83
+ assert_list arg
84
+ assert(arg.empty?)
85
+ end
86
+ ###
87
+ ### Assert that the elements of exp are the same as those of out,
88
+ ### and are in the same order.
89
+ ###
90
+ def assert_same_list exp, out
91
+ assert_equal(exp.length, out.length, "Checking length")
92
+ (0...exp.length).each do |i|
93
+ assert_same(exp[i], out[i], "At index #{i} (of 0...#{exp.length})")
94
+ end
95
+ end
96
+ ###
97
+ ### Assert that out is ==, but not the same as exp (i.e., it is a
98
+ ### copy).
99
+ ###
100
+ def assert_copy exp, out
101
+ assert_not_same exp, out
102
+ assert_equal exp, out
103
+ end
104
+ ###
105
+ ### Assert the invariants of `node'.
106
+ ###
107
+ def assert_invariants node
108
+ node.assert_invariants(self)
109
+ end
110
+ ###
111
+ ### Return a not-too-trivial C program string.
112
+ ###
113
+ def prog
114
+ return <<EOS
115
+ int main(int argc, char **argv) {
116
+ struct S {
117
+ int i, j;
118
+ float f, g;
119
+ } x;
120
+ x.i = (int)argv[2][5];
121
+ return 0;
122
+ }
123
+ EOS
124
+ end
125
+ end
126
+
127
+ module CheckAst
128
+ INDENT = ' '
129
+
130
+ ParseError = C::ParseError
131
+
132
+ def check_ast test_data
133
+ inp, exp = test_data.split(/^----+\n/)
134
+ ast = yield(inp)
135
+ assert_tree(ast)
136
+ assert ast.is_a?(C::Node)
137
+ out = ast.to_debug
138
+ assert_equal_debug_strs(exp, out)
139
+ end
140
+
141
+ def assert_equal_debug_strs exp, out
142
+ ## remove EOL space
143
+ out = out.gsub(/ *$/, '')
144
+ exp = exp.gsub(/ *$/, '')
145
+
146
+ ## normalize BOL space
147
+ exp.gsub!(%r'^#{INDENT}*') do |s|
148
+ levels = s.length / INDENT.length
149
+ C::Node::TO_DEBUG_TAB*levels
150
+ end
151
+
152
+ ## compare
153
+ meth = 'unknown method'
154
+ caller.each do |line|
155
+ if line =~ /in `(test_.*?)'/ #`
156
+ meth = $1
157
+ break
158
+ end
159
+ end
160
+
161
+ filename_prefix = "#{self.class}_#{meth}"
162
+
163
+ assert_block("Debug strings unequal. Output dumped to #{filename_prefix}.{exp,out}") do
164
+ if out == exp
165
+ true
166
+ else
167
+ classname = self.class.name.split(/::/)[-1]
168
+ open("#{filename_prefix}.out", 'w'){|f| f.print(out)}
169
+ open("#{filename_prefix}.exp", 'w'){|f| f.print(exp)}
170
+ false
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ Dir.new(Dir.pwd).grep(/^test_/) do |filename|
4
+ require "#{Dir.pwd}/#{filename}"
5
+ end
@@ -0,0 +1,160 @@
1
+ require 'common'
2
+
3
+ ###
4
+ ### ##################################################################
5
+ ###
6
+ ### Tests for miscellaneous methods specific to individual Node
7
+ ### classes.
8
+ ###
9
+ ### ##################################################################
10
+ ###
11
+ class MiscTests < Test::Unit::TestCase
12
+ include CheckAst
13
+
14
+ ###
15
+ ### ----------------------------------------------------------------
16
+ ### Declarator#
17
+ ### declaration type
18
+ ### ----------------------------------------------------------------
19
+ ###
20
+
21
+ def test_declarator_declaration
22
+ tor = C::Declarator.new(nil, 'x')
23
+ assert_nil(tor.declaration)
24
+
25
+ list = C::NodeArray[tor]
26
+ assert_nil(tor.declaration)
27
+
28
+ tion = C::Declaration.new(C::Int.new, list)
29
+ assert_same(tion, tor.declaration)
30
+
31
+ list.detach
32
+ assert_nil(tor.declaration)
33
+ end
34
+
35
+ def test_declarator_type
36
+ ## int i, *j, k[], l(), *m[10];
37
+ decl = C::Declaration.new(C::Int.new)
38
+ decl.declarators << C::Declarator.new(nil, 'i')
39
+ decl.declarators << C::Declarator.new(C::Pointer.new, 'j')
40
+ decl.declarators << C::Declarator.new(C::Array.new, 'k')
41
+ decl.declarators << C::Declarator.new(C::Function.new, 'l')
42
+ arr = C::Array.new(C::Pointer.new, C::IntLiteral.new(10))
43
+ decl.declarators << C::Declarator.new(arr, 'm')
44
+
45
+ assert_equal_debug_strs(decl.declarators[0].type.to_debug, <<EOS)
46
+ Int
47
+ EOS
48
+ assert_equal_debug_strs(decl.declarators[1].type.to_debug, <<EOS)
49
+ Pointer
50
+ type: Int
51
+ EOS
52
+ assert_equal_debug_strs(decl.declarators[2].type.to_debug, <<EOS)
53
+ Array
54
+ type: Int
55
+ EOS
56
+ assert_equal_debug_strs(decl.declarators[3].type.to_debug, <<EOS)
57
+ Function
58
+ type: Int
59
+ EOS
60
+ assert_equal_debug_strs(decl.declarators[4].type.to_debug, <<EOS)
61
+ Array
62
+ type: Pointer
63
+ type: Int
64
+ length: IntLiteral
65
+ val: 10
66
+ EOS
67
+ end
68
+
69
+ ###
70
+ ### ----------------------------------------------------------------
71
+ ### DirectType#
72
+ ### direct_type indirect_type
73
+ ### IndirectType#
74
+ ### direct_type indirect_type direct_type=
75
+ ### ----------------------------------------------------------------
76
+ ###
77
+
78
+ def test_type_direct_type
79
+ d = C::Int.new
80
+ t = C::Pointer.new(d)
81
+ assert_same(d, t.direct_type)
82
+
83
+ d = C::Float.new
84
+ t = C::Pointer.new(C::Pointer.new(d))
85
+ assert_same(d, t.direct_type)
86
+
87
+ d = C::Struct.new('S')
88
+ t = C::Array.new(d)
89
+ assert_same(d, t.direct_type)
90
+
91
+ d = C::CustomType.new('T')
92
+ t = C::Function.new(d)
93
+ assert_same(d, t.direct_type)
94
+
95
+ t = C::Pointer.new(nil)
96
+ assert_nil(t.direct_type)
97
+
98
+ t = C::Int.new
99
+ assert_same(t, t.direct_type)
100
+ end
101
+
102
+ def test_type_indirect_type
103
+ d = C::Int.new
104
+ t = C::Pointer.new(d)
105
+ assert_equal(C::Pointer.new, t.indirect_type)
106
+
107
+ d = C::Float.new
108
+ t = C::Pointer.new(C::Pointer.new(d))
109
+ assert_equal(C::Pointer.new(C::Pointer.new), t.indirect_type)
110
+
111
+ d = C::Struct.new('S')
112
+ t = C::Array.new(d, C::IntLiteral.new(10))
113
+ assert_equal(C::Array.new(nil, C::IntLiteral.new(10)), t.indirect_type)
114
+
115
+ d = C::CustomType.new('T')
116
+ t = C::Function.new(d)
117
+ assert_equal(C::Function.new, t.indirect_type)
118
+
119
+ t = C::Pointer.new(nil)
120
+ assert_copy(t, t.indirect_type)
121
+
122
+ t = C::Int.new
123
+ assert_nil(t.indirect_type)
124
+ end
125
+
126
+ def test_type_set_direct_type
127
+ d = C::Int.new
128
+ t = C::Pointer.new(d)
129
+ x = C::Int.new
130
+ t.direct_type = x
131
+ assert_same(x, t.type)
132
+
133
+ d = C::Float.new
134
+ t = C::Pointer.new(C::Pointer.new(d))
135
+ x = C::Float.new
136
+ t.direct_type = x
137
+ assert_same(x, t.type.type)
138
+
139
+ d = C::Struct.new('S')
140
+ t = C::Array.new(d)
141
+ x = C::Struct.new('T')
142
+ t.direct_type = x
143
+ assert_same(x, t.type)
144
+
145
+ d = C::CustomType.new('T')
146
+ t = C::Function.new(d)
147
+ x = C::Void.new
148
+ t.direct_type = x
149
+ assert_same(x, t.type)
150
+
151
+ t = C::Pointer.new(nil)
152
+ x = C::Imaginary.new
153
+ t.direct_type = x
154
+ assert_same(x, t.type)
155
+
156
+ t = C::Int.new
157
+ x = C::Void.new
158
+ assert_raise(NoMethodError){t.direct_type = x}
159
+ end
160
+ end
@@ -0,0 +1,1224 @@
1
+ ###
2
+ ### ##################################################################
3
+ ###
4
+ ### Tests for Node core functionality.
5
+ ###
6
+ ### ##################################################################
7
+ ###
8
+
9
+ require 'common'
10
+ require 'stringio'
11
+
12
+ require 'pp'
13
+ class C::Node
14
+ def pretty_print q
15
+ q.text self.to_debug
16
+ end
17
+ end
18
+
19
+ Chain = C::NodeChain
20
+
21
+ ###
22
+ ### Some Node classes.
23
+ ###
24
+ class X < C::Node
25
+ child :a
26
+ initializer :a
27
+ end
28
+ class Y < C::Node
29
+ child :a
30
+ child :b
31
+ initializer :a, :b
32
+ end
33
+ class Z < C::Node
34
+ child :a
35
+ field :b
36
+ child :c
37
+ field :d
38
+ child :e
39
+ initializer :a, :b, :c, :d, :e
40
+ end
41
+ class W < C::Node
42
+ field :a
43
+ field :b, 0
44
+ initializer :a, :b
45
+ end
46
+ class V < C::Node
47
+ child :a, lambda{C::NodeArray.new}
48
+ initializer :a
49
+ end
50
+
51
+ class NodeInitializeTest < Test::Unit::TestCase
52
+ ###
53
+ ### ----------------------------------------------------------------
54
+ ### initialize
55
+ ### ----------------------------------------------------------------
56
+ ###
57
+
58
+ def test_initialize_w
59
+ w = W.new
60
+ assert_nil(w.a)
61
+ assert_same(0, w.b)
62
+
63
+ w = W.new(1, true)
64
+ assert_same(1, w.a)
65
+ assert_same(true, w.b)
66
+
67
+ w = W.new(1, :b => true)
68
+ assert_same(1, w.a)
69
+ assert_same(true, w.b)
70
+
71
+ w = W.new(:a => 1, :b => true)
72
+ assert_same(1, w.a)
73
+ assert_same(true, w.b)
74
+ end
75
+
76
+ def test_initialize_v
77
+ v = V.new
78
+ assert_same_list([], v.a)
79
+ assert_same(C::NodeArray, v.a.class)
80
+
81
+ v = V.new(C::NodeChain[])
82
+ assert_same_list([], v.a)
83
+ assert_same(C::NodeChain, v.a.class)
84
+ end
85
+
86
+ def test_initialize_attached
87
+ x1, x2 = 2.of{X.new}
88
+ list = C::NodeArray[x1, x2]
89
+ z = Z.new(x1, x2)
90
+ assert_same_list([x1, x2], list)
91
+ assert_copy(x1, z.a)
92
+ assert_same(x2, z.b)
93
+ end
94
+
95
+ ###
96
+ ### ----------------------------------------------------------------
97
+ ### Node.new_at
98
+ ### ----------------------------------------------------------------
99
+ ###
100
+ def test_new_at
101
+ pos = C::Node::Pos.new('somefile', 5, 10)
102
+ xa = X.new
103
+ x = X.new_at(pos, xa)
104
+ assert_same(pos, x.pos)
105
+ assert_same(xa, x.a)
106
+ end
107
+ end
108
+
109
+ class NodeEqualTest < Test::Unit::TestCase
110
+ def str
111
+ "(struct s){.a = 1, [2] = {3, 4}, .b [5] = 6, 7}"
112
+ end
113
+ def node
114
+ ma = C::Member.new('a')
115
+ mb = C::Member.new('b')
116
+ one = C::IntLiteral.new(1)
117
+ two = C::IntLiteral.new(2)
118
+ three = C::IntLiteral.new(3)
119
+ four = C::IntLiteral.new(4)
120
+ five = C::IntLiteral.new(5)
121
+ six = C::IntLiteral.new(6)
122
+ seven = C::IntLiteral.new(7)
123
+
124
+ mi0 = C::MemberInit.new(Chain[ma], one)
125
+ mi10 = C::MemberInit.new(nil, three)
126
+ mi11 = C::MemberInit.new(nil, four)
127
+ mi1 = C::MemberInit.new(Chain[two],
128
+ C::CompoundLiteral.new(nil, Chain[mi10, mi11]))
129
+ mi2 = C::MemberInit.new(Chain[mb, five], six)
130
+ mi3 = C::MemberInit.new(nil, seven)
131
+
132
+ c = C::CompoundLiteral.new(C::Struct.new('s'),
133
+ Chain[mi0, mi1, mi2, mi3])
134
+ return c
135
+ end
136
+
137
+ ###
138
+ ### ----------------------------------------------------------------
139
+ ### ==, eql?
140
+ ### ----------------------------------------------------------------
141
+ ###
142
+ def test_eq
143
+ ## copy should be equal
144
+ assert_equal(node, node)
145
+ assert(node.eql?(node))
146
+
147
+ ## change any one field and it should be not_equal
148
+ n = node
149
+ n.type = nil
150
+ assert_not_equal(node, n)
151
+ assert(!node.eql?(n))
152
+
153
+ n = node
154
+ n.member_inits[0].member[0] = C::Member.new('c')
155
+ assert_not_equal(node, n)
156
+ assert(!node.eql?(n))
157
+ copy = node.dup
158
+
159
+ n = node
160
+ n.member_inits[2].member[1] = C::IntLiteral.new(8)
161
+ assert_not_equal(node, n)
162
+ assert(!node.eql?(n))
163
+
164
+ ## add a member's init and it should be not_equal
165
+ n = node
166
+ n.member_inits[3].init = C::IntLiteral.new(9)
167
+ assert_not_equal(node, n)
168
+ assert(!node.eql?(n))
169
+
170
+ ## change a member's init and it should be not_equal
171
+ n = node
172
+ n.member_inits[0].init = C::IntLiteral.new(10)
173
+ assert_not_equal(node, n)
174
+ assert(!node.eql?(n))
175
+
176
+ ## add a member specifier and it should be not_equal
177
+ n = node
178
+ n.member_inits[3].member = Chain[C::Member.new('d')]
179
+ assert_not_equal(node, n)
180
+ assert(!node.eql?(n))
181
+
182
+ ## pop a member and it should be not_equal
183
+ n = node
184
+ n.member_inits.pop
185
+ assert_not_equal(node, n)
186
+ assert(!node.eql?(n))
187
+
188
+ ## assign a field a copy of what's there and it should still be
189
+ ## equal
190
+ n = node
191
+ n.member_inits[0].member[0] = C::Member.new('a')
192
+ assert_equal(node, n)
193
+ assert(node.eql?(n))
194
+
195
+ n = node
196
+ n.member_inits[0].init = C::IntLiteral.new(1)
197
+ assert_equal(node, n)
198
+ assert(node.eql?(n))
199
+ end
200
+
201
+ ###
202
+ ### ----------------------------------------------------------------
203
+ ### hash
204
+ ### ----------------------------------------------------------------
205
+ ###
206
+ def test_hash
207
+ ## copy should be equal
208
+ assert_equal(node.hash, node.hash)
209
+
210
+ ## should be equal after assigning to a field a copy of what's
211
+ ## there
212
+ n = node
213
+ n.member_inits[0].member[0] = C::Member.new('a')
214
+ assert_equal(node.hash, n.hash)
215
+
216
+ n = node
217
+ n.member_inits[0].init = C::IntLiteral.new(1)
218
+ assert_equal(node.hash, n.hash)
219
+ end
220
+ end
221
+
222
+ class NodeCopyTest < Test::Unit::TestCase
223
+ def setup
224
+ ## (struct s){.a = 1, [2] = {3, 4}, .b [5] = 6, 7}
225
+
226
+
227
+
228
+ @c_t_n = 's'
229
+ @c_t = C::Struct.new(@c_t_n)
230
+
231
+ @c_mis0_m0_n = 'a'
232
+ @c_mis0_m0 = C::Member.new(@c_mis0_m0_n)
233
+ @c_mis0_m = Chain[@c_mis0_m0]
234
+ @c_mis0_i = C::IntLiteral.new(1)
235
+ @c_mis0 = C::MemberInit.new(@c_mis0_m, @c_mis0_i)
236
+
237
+ @c_mis1_m0 = C::IntLiteral.new(2)
238
+ @c_mis1_m = Chain[@c_mis1_m0]
239
+ @c_mis1_i_mis0_i = C::IntLiteral.new(3)
240
+ @c_mis1_i_mis0 = C::MemberInit.new(nil, @c_mis1_i_mis0_i)
241
+ @c_mis1_i_mis1_i = C::IntLiteral.new(4)
242
+ @c_mis1_i_mis1 = C::MemberInit.new(nil, @c_mis1_i_mis1_i)
243
+ @c_mis1_i_mis = Chain[@c_mis1_i_mis0, @c_mis1_i_mis1]
244
+ @c_mis1_i = C::CompoundLiteral.new(nil, @c_mis1_i_mis)
245
+ @c_mis1 = C::MemberInit.new(@c_mis1_m, @c_mis1_i)
246
+
247
+ @c_mis2_m0_n
248
+ @c_mis2_m0 = C::Member.new(@c_mis2_m0_n)
249
+ @c_mis2_m1 = C::IntLiteral.new(5)
250
+ @c_mis2_m = Chain[@c_mis2_m0, @c_mis2_m1]
251
+ @c_mis2_i = C::IntLiteral.new(6)
252
+ @c_mis2 = C::MemberInit.new(@c_mis2_m, @c_mis2_i)
253
+
254
+ @c_mis3_i = C::IntLiteral.new(7)
255
+ @c_mis3 = C::MemberInit.new(nil, @c_mis3_i)
256
+ @c_mis = Chain[@c_mis0, @c_mis1, @c_mis2, @c_mis3]
257
+
258
+ @c = C::CompoundLiteral.new(@c_t, @c_mis)
259
+
260
+ class << @c
261
+ def new_method
262
+ 100
263
+ end
264
+ end
265
+ class << @c_mis1_i_mis0
266
+ def new_method
267
+ 100
268
+ end
269
+ end
270
+
271
+ @d = c.dup
272
+ @e = c.clone
273
+ end
274
+ attr_accessor :c, :d, :e
275
+
276
+ ###
277
+ ### ----------------------------------------------------------------
278
+ ### dup, clone
279
+ ### ----------------------------------------------------------------
280
+ ###
281
+ def check_node value
282
+ cres = yield(c)
283
+ dres = yield(d)
284
+ eres = yield(e)
285
+ assert_same(value, cres)
286
+ if value.is_a? C::Node
287
+ assert_copy(value, dres)
288
+ assert_copy(value, eres)
289
+ else
290
+ assert_same(value, dres)
291
+ assert_same(value, eres)
292
+ end
293
+ assert_raise(NoMethodError){dres.new_method}
294
+ case value.object_id
295
+ when @c.object_id, @c_mis1_i_mis0.object_id
296
+ assert_same(100, eres.new_method)
297
+ else
298
+ assert_raise(NoMethodError){eres.new_method}
299
+ end
300
+ end
301
+
302
+ def test_copy
303
+ ## each element should be equal, but not the same, except for
304
+ ## immediate values
305
+ ##
306
+ ## (struct s){.a = 1, [2] = {3, 4}, .b [5] = 6, 7}
307
+ assert_tree(c)
308
+ assert_tree(d)
309
+ assert_tree(e)
310
+ check_node(@c ){|x| x}
311
+ check_node(@c_t ){|x| x.type}
312
+ check_node(@c_t_n ){|x| x.type.name}
313
+ check_node(nil ){|x| x.type.members}
314
+ check_node(@c_mis ){|x| x.member_inits}
315
+ check_node(@c_mis0 ){|x| x.member_inits[0]}
316
+ check_node(@c_mis0_m ){|x| x.member_inits[0].member}
317
+ check_node(@c_mis0_m0 ){|x| x.member_inits[0].member[0]}
318
+ check_node(@c_mis0_m0_n ){|x| x.member_inits[0].member[0].name}
319
+ check_node(@c_mis0_i ){|x| x.member_inits[0].init}
320
+ check_node(1 ){|x| x.member_inits[0].init.val}
321
+ check_node(@c_mis1 ){|x| x.member_inits[1]}
322
+ check_node(@c_mis1_m ){|x| x.member_inits[1].member}
323
+ check_node(@c_mis1_m0 ){|x| x.member_inits[1].member[0]}
324
+ check_node(2 ){|x| x.member_inits[1].member[0].val}
325
+ check_node(@c_mis1_i ){|x| x.member_inits[1].init}
326
+ check_node(nil ){|x| x.member_inits[1].init.type}
327
+ check_node(@c_mis1_i_mis ){|x| x.member_inits[1].init.member_inits}
328
+ check_node(@c_mis1_i_mis0 ){|x| x.member_inits[1].init.member_inits[0]}
329
+ check_node(nil ){|x| x.member_inits[1].init.member_inits[0].member}
330
+ check_node(@c_mis1_i_mis0_i){|x| x.member_inits[1].init.member_inits[0].init}
331
+ check_node(3 ){|x| x.member_inits[1].init.member_inits[0].init.val}
332
+ check_node(@c_mis1_i_mis1 ){|x| x.member_inits[1].init.member_inits[1]}
333
+ check_node(nil ){|x| x.member_inits[1].init.member_inits[1].member}
334
+ check_node(@c_mis1_i_mis1_i){|x| x.member_inits[1].init.member_inits[1].init}
335
+ check_node(4 ){|x| x.member_inits[1].init.member_inits[1].init.val}
336
+ check_node(@c_mis2 ){|x| x.member_inits[2]}
337
+ check_node(@c_mis2_m ){|x| x.member_inits[2].member}
338
+ check_node(@c_mis2_m0 ){|x| x.member_inits[2].member[0]}
339
+ check_node(@c_mis2_m0_n ){|x| x.member_inits[2].member[0].name}
340
+ check_node(@c_mis2_m1 ){|x| x.member_inits[2].member[1]}
341
+ check_node(5 ){|x| x.member_inits[2].member[1].val}
342
+ check_node(@c_mis2_i ){|x| x.member_inits[2].init}
343
+ check_node(6 ){|x| x.member_inits[2].init.val}
344
+ check_node(@c_mis3 ){|x| x.member_inits[3]}
345
+ check_node(nil ){|x| x.member_inits[3].member}
346
+ check_node(@c_mis3_i ){|x| x.member_inits[3].init}
347
+ check_node(7 ){|x| x.member_inits[3].init.val}
348
+ end
349
+ end
350
+
351
+ class NodeWalkTest < Test::Unit::TestCase
352
+ ###
353
+ ### Collect and return the args yielded to `node.send(method)' as an
354
+ ### Array, each element of which is an array of args yielded.
355
+ ###
356
+ ### Also, assert that the return value of the method is `exp'.
357
+ ###
358
+ def yields method, node, exp
359
+ ret = []
360
+ out = node.send(method) do |*args|
361
+ ret << args
362
+ yield *args if block_given?
363
+ end
364
+ assert_same(exp, out)
365
+ return ret
366
+ end
367
+
368
+ ###
369
+ ### Assert exp and out are equal, where elements are compared with
370
+ ### Array#same_list?. That is, exp[i].same_list?(out[i]) for all i.
371
+ ###
372
+ def assert_equal_yields exp, out
373
+ if exp.zip(out).all?{|a,b| a.same_list?(b)}
374
+ assert(true)
375
+ else
376
+ flunk("walk not equal: #{walk_str(out)} (expected #{walk_str(exp)})")
377
+ end
378
+ end
379
+ def walk_str walk
380
+ walk.is_a? ::Array or
381
+ raise "walk_str: expected ::Array"
382
+ if walk.empty?
383
+ return '[]'
384
+ else
385
+ s = StringIO.new
386
+ s.puts '['
387
+ walk.each do |args|
388
+ args.map! do |arg|
389
+ if arg.is_a? C::Node
390
+ argstr = arg.class.name << ' (' << arg.object_id.to_s <<
391
+ "): " << arg.to_s
392
+ else
393
+ argstr = arg.inspect
394
+ end
395
+ if argstr.length > 50
396
+ argstr[48..-1] = '...'
397
+ end
398
+ argstr
399
+ end
400
+ s.puts " [#{args.join(', ')}]"
401
+ end
402
+ s.puts ']'
403
+ return s.string
404
+ end
405
+ end
406
+
407
+ ###
408
+ ### ----------------------------------------------------------------
409
+ ### depth_first, reverse_depth_first
410
+ ### ----------------------------------------------------------------
411
+ ###
412
+ def check_depth_firsts node, exp
413
+ ## depth_first
414
+ out = yields(:depth_first, node, node)
415
+ assert_equal_yields exp, out
416
+
417
+ ## reverse_depth_first
418
+ exp = exp.reverse.map! do |ev, node|
419
+ if ev == :ascending
420
+ [:descending, node]
421
+ else
422
+ [:ascending, node]
423
+ end
424
+ end
425
+ out = yields(:reverse_depth_first, node, node)
426
+ assert_equal_yields exp, out
427
+ end
428
+
429
+ def test_depth_first
430
+ ## empty node
431
+ d = C::Int.new
432
+ d.longness = 1
433
+ check_depth_firsts(d,
434
+ [[:descending, d], [:ascending, d]])
435
+
436
+ ## one-storey -- populate both the list child and nonlist child
437
+ d = C::Declaration.new(C::Int.new)
438
+ d.declarators << C::Declarator.new
439
+ d.declarators[0].name = 'one'
440
+ d.declarators << C::Declarator.new
441
+ d.declarators[1].name = 'two'
442
+ check_depth_firsts(d,
443
+ [
444
+ [:descending, d],
445
+ [:descending, d.type], [:ascending, d.type],
446
+ [:descending, d.declarators],
447
+ [:descending, d.declarators[0]], [:ascending, d.declarators[0]],
448
+ [:descending, d.declarators[1]], [:ascending, d.declarators[1]],
449
+ [:ascending, d.declarators],
450
+ [:ascending, d]
451
+ ])
452
+
453
+ ## multi-layer
454
+ d.declarators[0].indirect_type = C::Function.new
455
+ d.declarators[0].indirect_type.params = Chain[]
456
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Int.new, 'i')
457
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Float.new, 'f')
458
+ check_depth_firsts(d,
459
+ [
460
+ [:descending, d],
461
+ [:descending, d.type], [:ascending, d.type],
462
+ [:descending, d.declarators],
463
+ [:descending, d.declarators[0]],
464
+ [:descending, d.declarators[0].indirect_type],
465
+ [:descending, d.declarators[0].indirect_type.params],
466
+ [:descending, d.declarators[0].indirect_type.params[0]],
467
+ [:descending, d.declarators[0].indirect_type.params[0].type], [:ascending, d.declarators[0].indirect_type.params[0].type],
468
+ [:ascending, d.declarators[0].indirect_type.params[0]],
469
+ [:descending, d.declarators[0].indirect_type.params[1]],
470
+ [:descending, d.declarators[0].indirect_type.params[1].type], [:ascending, d.declarators[0].indirect_type.params[1].type],
471
+ [:ascending, d.declarators[0].indirect_type.params[1]],
472
+ [:ascending, d.declarators[0].indirect_type.params],
473
+ [:ascending, d.declarators[0].indirect_type],
474
+ [:ascending, d.declarators[0]],
475
+ [:descending, d.declarators[1]], [:ascending, d.declarators[1]],
476
+ [:ascending, d.declarators],
477
+ [:ascending, d]
478
+ ])
479
+ end
480
+
481
+ def check_depth_first_prunes pruned_nodes, node, exp
482
+ ## depth_first
483
+ out = yields(:depth_first, node, node) do |ev, node|
484
+ if ev.equal? :descending
485
+ if pruned_nodes.any?{|n| n.equal? node}
486
+ throw :prune
487
+ end
488
+ end
489
+ end
490
+ assert_equal_yields exp, out
491
+ ##
492
+ ret = catch :prune do
493
+ node.depth_first do |ev, node|
494
+ throw :prune, :x if ev.equal? :ascending
495
+ end
496
+ :oops
497
+ end
498
+ assert_same(:x, ret)
499
+
500
+ ## reverse_depth_first
501
+ exp = exp.reverse.map! do |ev, node|
502
+ if ev.equal? :ascending
503
+ [:descending, node]
504
+ else
505
+ [:ascending, node]
506
+ end
507
+ end
508
+ out = yields(:reverse_depth_first, node, node) do |ev, node|
509
+ if ev.equal? :descending
510
+ if pruned_nodes.any?{|n| n.equal? node}
511
+ throw :prune
512
+ end
513
+ end
514
+ end
515
+ assert_equal_yields exp, out
516
+ ##
517
+ ret = catch :prune do
518
+ node.reverse_depth_first do |ev, node|
519
+ throw :prune, :x if ev.equal? :ascending
520
+ end
521
+ :oops
522
+ end
523
+ assert_same(:x, ret)
524
+ end
525
+
526
+ def test_depth_first_prune
527
+ ## empty node
528
+ d = C::Int.new
529
+ d.longness = 1
530
+ check_depth_first_prunes([d], d,
531
+ [[:descending, d], [:ascending, d]])
532
+
533
+ ## one-storey -- populate both the list child and nonlist child
534
+ d = C::Declaration.new(C::Int.new)
535
+ d.declarators << C::Declarator.new
536
+ d.declarators[0].name = 'one'
537
+ d.declarators << C::Declarator.new
538
+ d.declarators[1].name = 'two'
539
+ check_depth_first_prunes([d.declarators], d,
540
+ [
541
+ [:descending, d],
542
+ [:descending, d.type], [:ascending, d.type],
543
+ [:descending, d.declarators], [:ascending, d.declarators],
544
+ [:ascending, d]
545
+ ])
546
+
547
+ ## multi-layer
548
+ d.type = C::Struct.new('S')
549
+ d.type.members = Chain[]
550
+ d.type.members << C::Declaration.new(C::Int.new)
551
+ d.type.members[0].declarators << C::Declarator.new(nil, 'x')
552
+ d.declarators[0].indirect_type = C::Function.new
553
+ d.declarators[0].indirect_type.params = Chain[]
554
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Int.new, 'i')
555
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Float.new, 'f')
556
+ check_depth_first_prunes([d.type.members, d.declarators[0]], d,
557
+ [
558
+ [:descending, d],
559
+ [:descending, d.type],
560
+ [:descending, d.type.members], [:ascending, d.type.members],
561
+ [:ascending, d.type],
562
+ [:descending, d.declarators],
563
+ [:descending, d.declarators[0]], [:ascending, d.declarators[0]],
564
+ [:descending, d.declarators[1]], [:ascending, d.declarators[1]],
565
+ [:ascending, d.declarators],
566
+ [:ascending, d]
567
+ ])
568
+ end
569
+
570
+ ###
571
+ ### ----------------------------------------------------------------
572
+ ### each, reverse_each
573
+ ### ----------------------------------------------------------------
574
+ ###
575
+
576
+ def iter_str iter
577
+ iter.is_a? ::Array or
578
+ raise "iter_str: expected ::Array"
579
+ if iter.empty?
580
+ return '[]'
581
+ else
582
+ s = StringIO.new
583
+ s.puts '['
584
+ iter.each do |node|
585
+ nodestr = node.class.name << '(' << node.object_id.to_s << "): " << node.to_s
586
+ if nodestr.length > 70
587
+ nodestr[68..-1] = '...'
588
+ end
589
+ s.puts " #{nodestr}"
590
+ end
591
+ s.puts ']'
592
+ return s.string
593
+ end
594
+ end
595
+ def check_each node, exp
596
+ exp.map!{|n| [n]}
597
+
598
+ out = yields(:each, node, node)
599
+ assert_equal_yields exp, out
600
+
601
+ out = yields(:reverse_each, node, node)
602
+ exp.reverse!
603
+ assert_equal_yields exp, out
604
+ end
605
+ def test_each
606
+ ## empty
607
+ parent = X.new
608
+ check_each(parent, [])
609
+
610
+ ## one child
611
+ x1 = X.new
612
+ parent = X.new(x1)
613
+ check_each(parent, [x1])
614
+
615
+ ## two children
616
+ x1, x2 = 2.of{X.new}
617
+ parent = Y.new(x1, x2)
618
+ check_each(parent, [x1, x2])
619
+
620
+ ## three with some nil and some fields
621
+ x1, x2, x3, x4, x5 = 5.of{X.new}
622
+ parent = Z.new(x1, x2, nil, x4, x5)
623
+ check_each(parent, [x1, x5])
624
+ end
625
+
626
+ ###
627
+ ### ----------------------------------------------------------------
628
+ ### preorder, reverse_preorder
629
+ ### postorder, reverse_postorder
630
+ ### ----------------------------------------------------------------
631
+ ###
632
+
633
+ def check_preorder node, exp
634
+ exp.map!{|n| [n]}
635
+
636
+ out = yields(:preorder, node, node)
637
+ assert_equal_yields exp, out
638
+
639
+ out = yields(:reverse_postorder, node, node)
640
+ exp.reverse!
641
+ assert_equal_yields exp, out
642
+ end
643
+ def check_postorder node, exp
644
+ exp.map!{|n| [n]}
645
+
646
+ out = yields(:postorder, node, node)
647
+ assert_equal_yields exp, out
648
+
649
+ out = yields(:reverse_preorder, node, node)
650
+ exp.reverse!
651
+ assert_equal_yields exp, out
652
+ end
653
+ def test_preorder
654
+ ## empty node
655
+ d = C::Int.new
656
+ d.longness = 1
657
+ check_preorder(d, [d])
658
+
659
+ ## one-storey -- populate both the list child and nonlist child
660
+ d = C::Declaration.new(C::Int.new)
661
+ d.declarators << C::Declarator.new
662
+ d.declarators[0].name = 'one'
663
+ d.declarators << C::Declarator.new
664
+ d.declarators[1].name = 'two'
665
+ check_preorder(d,
666
+ [
667
+ d,
668
+ d.type,
669
+ d.declarators,
670
+ d.declarators[0],
671
+ d.declarators[1]
672
+ ])
673
+
674
+ ## multi-layer
675
+ d.declarators[0].indirect_type = C::Function.new
676
+ d.declarators[0].indirect_type.params = Chain[]
677
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Int.new, 'i')
678
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Float.new, 'f')
679
+ check_preorder(d,
680
+ [
681
+ d,
682
+ d.type,
683
+ d.declarators,
684
+ d.declarators[0],
685
+ d.declarators[0].indirect_type,
686
+ d.declarators[0].indirect_type.params,
687
+ d.declarators[0].indirect_type.params[0],
688
+ d.declarators[0].indirect_type.params[0].type,
689
+ d.declarators[0].indirect_type.params[1],
690
+ d.declarators[0].indirect_type.params[1].type,
691
+ d.declarators[1]
692
+ ])
693
+ end
694
+ def test_postorder
695
+ ## empty node
696
+ d = C::Int.new
697
+ d.longness = 1
698
+ check_preorder(d, [d])
699
+
700
+ ## one-storey -- populate both the list child and nonlist child
701
+ d = C::Declaration.new(C::Int.new)
702
+ d.declarators << C::Declarator.new
703
+ d.declarators[0].name = 'one'
704
+ d.declarators << C::Declarator.new
705
+ d.declarators[1].name = 'two'
706
+ check_postorder(d,
707
+ [
708
+ d.type,
709
+ d.declarators[0],
710
+ d.declarators[1],
711
+ d.declarators,
712
+ d
713
+ ])
714
+
715
+ ## multi-layer
716
+ d.declarators[0].indirect_type = C::Function.new
717
+ d.declarators[0].indirect_type.params = Chain[]
718
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Int.new, 'i')
719
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Float.new, 'f')
720
+ check_postorder(d,
721
+ [
722
+ d.type,
723
+ d.declarators[0].indirect_type.params[0].type,
724
+ d.declarators[0].indirect_type.params[0],
725
+ d.declarators[0].indirect_type.params[1].type,
726
+ d.declarators[0].indirect_type.params[1],
727
+ d.declarators[0].indirect_type.params,
728
+ d.declarators[0].indirect_type,
729
+ d.declarators[0],
730
+ d.declarators[1],
731
+ d.declarators,
732
+ d
733
+ ])
734
+ end
735
+ def check_preorder_prune method, pruned_nodes, root, exp
736
+ exp.map!{|n| [n]}
737
+
738
+ out = yields(method, root, root) do |node|
739
+ if pruned_nodes.any?{|n| n.equal? node}
740
+ throw :prune
741
+ end
742
+ end
743
+ assert_equal_yields exp, out
744
+ end
745
+
746
+ def test_preorder_prune
747
+ ## empty node
748
+ d = C::Int.new
749
+ d.longness = 1
750
+ check_preorder_prune(:preorder, [d], d, [d])
751
+ check_preorder_prune(:reverse_preorder, [d], d, [d])
752
+
753
+ ## one-storey -- populate both the list child and nonlist child
754
+ d = C::Declaration.new(C::Int.new)
755
+ d.declarators << C::Declarator.new
756
+ d.declarators[0].name = 'one'
757
+ d.declarators << C::Declarator.new
758
+ d.declarators[1].name = 'two'
759
+ check_preorder_prune(:preorder, [d.declarators], d,
760
+ [
761
+ d,
762
+ d.type,
763
+ d.declarators,
764
+ ])
765
+ check_preorder_prune(:reverse_preorder, [d.declarators], d,
766
+ [
767
+ d,
768
+ d.declarators,
769
+ d.type,
770
+ ])
771
+
772
+ ## multi-layer
773
+ d.type = C::Struct.new('S')
774
+ d.type.members = Chain[]
775
+ d.type.members << C::Declaration.new(C::Int.new)
776
+ d.type.members[0].declarators << C::Declarator.new(nil, 'x')
777
+ d.declarators[0].indirect_type = C::Function.new
778
+ d.declarators[0].indirect_type.params = Chain[]
779
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Int.new, 'i')
780
+ d.declarators[0].indirect_type.params << C::Parameter.new(C::Float.new, 'f')
781
+ check_preorder_prune(:preorder, [d.type.members, d.declarators[0]], d,
782
+ [
783
+ d,
784
+ d.type,
785
+ d.type.members,
786
+ d.declarators,
787
+ d.declarators[0],
788
+ d.declarators[1]
789
+ ])
790
+ check_preorder_prune(:reverse_preorder, [d.type.members, d.declarators[0]], d,
791
+ [
792
+ d,
793
+ d.declarators,
794
+ d.declarators[1],
795
+ d.declarators[0],
796
+ d.type,
797
+ d.type.members
798
+ ])
799
+ end
800
+
801
+ ###
802
+ ### ----------------------------------------------------------------
803
+ ### next, prev, list_next, list_prev
804
+ ### ----------------------------------------------------------------
805
+ ###
806
+
807
+ def test_next_prev
808
+ ## list parent
809
+ i1 = C::Int.new
810
+ i2 = C::Int.new
811
+ list = Chain[i1, i2]
812
+ assert_same(i2, i1.next)
813
+ assert_nil(i2.next)
814
+ assert_same(i1, i2.prev)
815
+ assert_nil(i1.prev)
816
+
817
+ ## node parent
818
+ i1 = C::IntLiteral.new(1)
819
+ i2 = C::IntLiteral.new(2)
820
+ a = C::Add.new(i1, i2)
821
+ assert_same(i2, i1.next)
822
+ assert_nil(i2.next)
823
+ assert_same(i1, i2.prev)
824
+ assert_nil(i1.prev)
825
+
826
+ ## no parent
827
+ i = C::Int.new
828
+ assert_raise(C::Node::NoParent){i.next}
829
+ assert_raise(C::Node::NoParent){i.prev}
830
+ end
831
+
832
+ def test_list_next_prev
833
+ ## list parent
834
+ i1 = C::Int.new
835
+ i2 = C::Int.new
836
+ list = Chain[i1, i2]
837
+ assert_same(i2, i1.list_next)
838
+ assert_nil(i2.list_next)
839
+ assert_same(i1, i2.list_prev)
840
+ assert_nil(i1.list_prev)
841
+
842
+ ## node parent
843
+ i1 = C::IntLiteral.new(1)
844
+ i2 = C::IntLiteral.new(2)
845
+ a = C::Add.new(i1, i2)
846
+ assert_raise(C::Node::BadParent){i1.list_next}
847
+ assert_raise(C::Node::BadParent){i2.list_next}
848
+ assert_raise(C::Node::BadParent){i1.list_prev}
849
+ assert_raise(C::Node::BadParent){i2.list_prev}
850
+
851
+ ## no parent
852
+ i = C::Int.new
853
+ assert_raise(C::Node::NoParent){i.list_next}
854
+ assert_raise(C::Node::NoParent){i.list_prev}
855
+ end
856
+ end
857
+
858
+ class NodeTreeTest < Test::Unit::TestCase
859
+ def setup
860
+ ## @c = "(int){[1] = 10,
861
+ ## .x = 20,
862
+ ## [2] .y = 30
863
+ ## }
864
+ @c = C::CompoundLiteral.new
865
+ c.type = C::Int.new
866
+ c.member_inits << C::MemberInit.new
867
+ c.member_inits[0].member = C::NodeChain.new
868
+ c.member_inits[0].member << C::IntLiteral.new(1)
869
+ c.member_inits[0].init = C::IntLiteral.new(10)
870
+ c.member_inits << C::MemberInit.new
871
+ c.member_inits[1].member = C::NodeChain.new
872
+ c.member_inits[1].member << C::Member.new('x')
873
+ c.member_inits[1].init = C::IntLiteral.new(20)
874
+ c.member_inits << C::MemberInit.new
875
+ c.member_inits[2].member = C::NodeChain.new
876
+ c.member_inits[2].member << C::IntLiteral.new(2)
877
+ c.member_inits[2].member << C::Member.new('y')
878
+ c.member_inits[2].init = C::IntLiteral.new(30)
879
+ end
880
+ attr_reader :c
881
+
882
+ def test_empty
883
+ ast = C::TranslationUnit.new
884
+ assert_tree(ast)
885
+ end
886
+ def test_basic
887
+ assert_tree(c)
888
+ end
889
+
890
+ def test_assign_field
891
+ c.type.unsigned = true
892
+ assert_tree(c)
893
+ assert_same(true, c.type.unsigned?)
894
+ c.type.unsigned = false
895
+ assert_tree(c)
896
+ assert_same(false, c.type.unsigned?)
897
+ end
898
+ def test_assign_child
899
+ c.type = nil
900
+ assert_tree(c)
901
+ assert_nil(c.type)
902
+ f = C::Float.new
903
+ c.type = f
904
+ assert_tree(c)
905
+ assert_same(f, c.type)
906
+ end
907
+ def test_assign_list
908
+ old_list = c.member_inits[2].member
909
+ new_list = C::NodeChain[C::IntLiteral.new(4), C::Member.new('a')]
910
+ c.member_inits[2].member = new_list
911
+ assert_tree(c)
912
+ assert_tree(old_list)
913
+ assert_same(new_list, c.member_inits[2].member)
914
+ end
915
+ def test_assign_attached
916
+ f = C::Float.new
917
+ c2 = C::CompoundLiteral.new
918
+ c2.type = f
919
+
920
+ c.type = f
921
+ assert_same(f, c2.type)
922
+ assert_copy(f, c.type)
923
+ assert_tree(c)
924
+ assert_tree(c2)
925
+ end
926
+
927
+ def test_detach_node
928
+ d = c.type.detach
929
+ assert_tree(c)
930
+ assert_tree(d)
931
+ end
932
+
933
+ def test_detach_list_element
934
+ member_one = c.member_inits[1]
935
+ member_two = c.member_inits[2]
936
+ d = c.member_inits[0].detach
937
+ assert_tree(c)
938
+ assert_tree(d)
939
+ assert_same_list([member_one, member_two], c.member_inits)
940
+ end
941
+
942
+ def test_detach_list
943
+ d = c.member_inits.detach
944
+ assert_tree(c)
945
+ assert_tree(d)
946
+ end
947
+
948
+ def test_node_replace_with
949
+ i = C::Int.new
950
+ t = c.type
951
+ assert_same(c.type, c.type.replace_with(i))
952
+ assert_tree(c)
953
+ assert_tree(t)
954
+ assert_same(i, c.type)
955
+
956
+ assert_same(c.type, c.type.replace_with(nil))
957
+ assert_tree(c)
958
+ assert_nil(c.type)
959
+ end
960
+ def test_node_replace_with_none
961
+ t = c.type
962
+ assert_same(c.type, c.type.replace_with)
963
+ assert_tree(c)
964
+ assert_tree(t)
965
+ assert_nil(c.type)
966
+ end
967
+ def test_node_replace_with_many
968
+ mi = c.member_inits[0]
969
+ mis = [c.member_inits[0], c.member_inits[1], c.member_inits[2]]
970
+
971
+ mi1 = C::MemberInit.new
972
+ mi1.init = C::IntLiteral.new(1)
973
+ mi2 = C::MemberInit.new
974
+ mi2.init = C::IntLiteral.new(2)
975
+
976
+ assert_same(mi, mi.replace_with(mi1, mi2))
977
+ assert_tree(c)
978
+ assert_tree(mi)
979
+ assert_same_list([mi1, mi2, mis[1], mis[2]], c.member_inits)
980
+
981
+ assert_raise(C::Node::NoParent){mi.replace_with(nil)}
982
+ i1 = C::Int.new
983
+ i2 = C::Int.new
984
+ assert_raise(ArgumentError){c.type.replace_with(i1, i2)}
985
+ end
986
+
987
+ def test_node_swap_with
988
+ ## swap with itself -- attached
989
+ x = X.new
990
+ parent = X.new(x)
991
+ assert_same(x, x.swap_with(x))
992
+ assert_same(parent, x.parent)
993
+ assert_same(x, parent.a)
994
+
995
+ ## swap with itself -- detached
996
+ x = X.new
997
+ assert_same(x, x.swap_with(x))
998
+ assert_nil(x.parent)
999
+
1000
+ ## both attached
1001
+ x = X.new
1002
+ y = X.new
1003
+ xp = X.new(x)
1004
+ yp = X.new(y)
1005
+ assert_same(x, x.swap_with(y))
1006
+ assert_same(xp, y.parent)
1007
+ assert_same(x, yp.a)
1008
+ assert_same(yp, x.parent)
1009
+ assert_same(y, xp.a)
1010
+
1011
+ ## only receiver attached
1012
+ x = X.new
1013
+ y = X.new
1014
+ xp = X.new(x)
1015
+ assert_same(x, x.swap_with(y))
1016
+ assert_nil(x.parent)
1017
+ assert_same(xp, y.parent)
1018
+ assert_same(y, xp.a)
1019
+
1020
+ ## only arg attached
1021
+ x = X.new
1022
+ y = X.new
1023
+ yp = X.new(y)
1024
+ assert_same(x, x.swap_with(y))
1025
+ assert_same(yp, x.parent)
1026
+ assert_same(x, yp.a)
1027
+ assert_nil(y.parent)
1028
+
1029
+ ## neither attached
1030
+ x = X.new
1031
+ y = X.new
1032
+ assert_same(x, x.swap_with(y))
1033
+ assert_nil(x.parent)
1034
+ assert_nil(y.parent)
1035
+ end
1036
+
1037
+ ###
1038
+ ### ----------------------------------------------------------------
1039
+ ### insert_next, insert_prev
1040
+ ### ----------------------------------------------------------------
1041
+ ###
1042
+ def test_node_insert_next_detached
1043
+ x1, x2 = 2.of{X.new}
1044
+ assert_raise(C::Node::NoParent){x1.insert_next}
1045
+ assert_nil(x1.parent)
1046
+ assert_raise(C::Node::NoParent){x1.insert_next(x2)}
1047
+ assert_nil(x1.parent)
1048
+ assert_nil(x2.parent)
1049
+ end
1050
+ def test_node_insert_next_nonlist_parent
1051
+ parent = X.new
1052
+ x1, x2 = 2.of{X.new}
1053
+ parent.a = x1
1054
+ assert_raise(C::Node::BadParent){x1.insert_next}
1055
+ assert_same(parent, x1.parent)
1056
+ assert_raise(C::Node::BadParent){x1.insert_next(x2)}
1057
+ assert_same(parent, x1.parent)
1058
+ assert_nil(x2.parent)
1059
+ end
1060
+ def test_node_insert_next_none
1061
+ x1 = X.new
1062
+ parent = Chain[x1]
1063
+ assert_same(x1, x1.insert_next)
1064
+ assert_same_list([x1], parent)
1065
+ end
1066
+ def test_node_insert_next_many
1067
+ x1, x2, x3, x4 = 4.of{X.new}
1068
+ parent = Chain[x1]
1069
+ assert_same(x1, x1.insert_next(x2, x3, x4))
1070
+ assert_same_list([x1, x2, x3, x4], parent)
1071
+ end
1072
+
1073
+ def test_node_insert_prev_detached
1074
+ a1, a2 = 2.of{X.new}
1075
+ assert_raise(C::Node::NoParent){a1.insert_prev}
1076
+ assert_nil(a1.parent)
1077
+ assert_raise(C::Node::NoParent){a1.insert_prev(a2)}
1078
+ assert_nil(a1.parent)
1079
+ assert_nil(a2.parent)
1080
+ end
1081
+ def test_node_insert_prev_nonlist_parent
1082
+ parent = X.new
1083
+ x1, x2 = 2.of{X.new}
1084
+ parent.a = x1
1085
+ assert_raise(C::Node::BadParent){x1.insert_prev}
1086
+ assert_same(parent, x1.parent)
1087
+ assert_raise(C::Node::BadParent){x1.insert_prev(x2)}
1088
+ assert_same(parent, x1.parent)
1089
+ assert_nil(x2.parent)
1090
+ end
1091
+ def test_node_insert_prev_none
1092
+ x1 = X.new
1093
+ parent = Chain[x1]
1094
+ assert_same(x1, x1.insert_prev)
1095
+ assert_same_list([x1], parent)
1096
+ end
1097
+ def test_node_insert_prev_many
1098
+ x1, x2, x3, x4 = 4.of{X.new}
1099
+ parent = Chain[x1]
1100
+ assert_same(x1, x1.insert_prev(x2, x3, x4))
1101
+ assert_same_list([x2, x3, x4, x1], parent)
1102
+ end
1103
+
1104
+ ###
1105
+ ### ----------------------------------------------------------------
1106
+ ### node_after, node_before
1107
+ ### ----------------------------------------------------------------
1108
+ ###
1109
+
1110
+ def test_node_after_before
1111
+ ## node not a child
1112
+ x1, x2 = 2.of{X.new}
1113
+ parent = X.new(x1)
1114
+ assert_raise(ArgumentError){parent.node_after(x2)}
1115
+ assert_raise(ArgumentError){parent.node_before(x2)}
1116
+
1117
+ x1, x2 = 2.of{X.new}
1118
+ parent = Z.new(nil, x1, nil, x2, nil)
1119
+ assert_raise(ArgumentError){parent.node_after(x1)}
1120
+ assert_raise(ArgumentError){parent.node_after(x2)}
1121
+ assert_raise(ArgumentError){parent.node_before(x1)}
1122
+ assert_raise(ArgumentError){parent.node_before(x2)}
1123
+
1124
+ ## one child
1125
+ x = X.new
1126
+ parent = X.new(x)
1127
+ assert_nil(parent.node_after(x))
1128
+ assert_nil(parent.node_before(x))
1129
+
1130
+ ## two children
1131
+ x1 = X.new
1132
+ x2 = X.new
1133
+ parent = Y.new(x1, x2)
1134
+ assert_same(x2, parent.node_after(x1))
1135
+ assert_nil(parent.node_after(x2))
1136
+ assert_same(x1, parent.node_before(x2))
1137
+ assert_nil(parent.node_before(x1))
1138
+
1139
+ ## skip over stuff in the middle
1140
+ x1, x2, x3, x4, x5 = 5.of{X.new}
1141
+ parent = Z.new(x1, x2, nil, x4, x5)
1142
+ assert_same(x5, parent.node_after(x1))
1143
+ assert_nil(parent.node_after(x5))
1144
+ assert_same(x1, parent.node_before(x5))
1145
+ assert_nil(parent.node_before(x1))
1146
+
1147
+ ## skip over stuff at the end
1148
+ x1, x2, x3, x4, x5 = 5.of{X.new}
1149
+ parent = Z.new(nil, x2, x3, x4, nil)
1150
+ assert_nil(parent.node_after(x3))
1151
+ assert_nil(parent.node_before(x3))
1152
+ end
1153
+
1154
+ def test_remove_node
1155
+ ## node not a child
1156
+ x1, x2, x3 = 3.of{X.new}
1157
+ parent = Z.new(x1, x2)
1158
+ assert_raise(ArgumentError){parent.remove_node(x2)}
1159
+ assert_raise(ArgumentError){parent.remove_node(x3)}
1160
+
1161
+ ## one child
1162
+ x = X.new
1163
+ parent = X.new(x)
1164
+ assert_same(parent, parent.remove_node(x))
1165
+ assert_tree(parent)
1166
+ assert_tree(x)
1167
+
1168
+ ## two children
1169
+ x1, x2 = 2.of{X.new}
1170
+ parent = Y.new(x1, x2)
1171
+ assert_same(parent, parent.remove_node(x2))
1172
+ assert_tree(parent)
1173
+ assert_tree(x2)
1174
+ assert_same(x1, parent.a)
1175
+ assert_nil(parent.b)
1176
+ end
1177
+
1178
+ def test_replace_node
1179
+ ## node not a child
1180
+ x1, x2, x3, x4 = 3.of{X.new}
1181
+ parent = Z.new(x1, x2)
1182
+ assert_raise(ArgumentError){parent.replace_node(x2, x4)}
1183
+ assert_raise(ArgumentError){parent.replace_node(x3, x4)}
1184
+
1185
+ ## no newnode
1186
+ x = X.new
1187
+ parent = X.new(x)
1188
+ assert_same(parent, parent.replace_node(x))
1189
+ assert_tree(parent)
1190
+ assert_tree(x)
1191
+ assert_nil(parent.a)
1192
+
1193
+ ## >1 newnode
1194
+ x1, x2, x3 = 3.of{X.new}
1195
+ parent = X.new(x1)
1196
+ assert_raise(ArgumentError){parent.replace_node(x1, x2, x3)}
1197
+
1198
+ ## one child
1199
+ x1, x2 = 2.of{X.new}
1200
+ parent = X.new(x1)
1201
+ assert_same(parent, parent.replace_node(x1, x2))
1202
+ assert_tree(parent)
1203
+ assert_tree(x1)
1204
+ assert_same(x2, parent.a)
1205
+ ##
1206
+ assert_same(parent, parent.replace_node(x2, nil))
1207
+ assert_tree(parent)
1208
+ assert_tree(x2)
1209
+ assert_nil(parent.a)
1210
+
1211
+ ## two children
1212
+ x1, x2, x3 = 3.of{X.new}
1213
+ parent = Y.new(x1, x2)
1214
+ assert_same(parent, parent.replace_node(x2, x3))
1215
+ assert_tree(parent)
1216
+ assert_tree(x2)
1217
+ assert_same(x3, parent.b)
1218
+ ##
1219
+ assert_same(parent, parent.replace_node(x3, nil))
1220
+ assert_tree(parent)
1221
+ assert_tree(x3)
1222
+ assert_nil(parent.b)
1223
+ end
1224
+ end