cast 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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