structx 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,284 @@
1
+ # -*- coding: us-ascii -*-
2
+ require 'test/unit'
3
+ require 'timeout'
4
+ require_relative 'envutil'
5
+
6
+ class TestStruct < Test::Unit::TestCase
7
+ def test_struct
8
+ struct_test = Struct.new("Test", :foo, :bar)
9
+ assert_equal(Struct::Test, struct_test)
10
+
11
+ test = struct_test.new(1, 2)
12
+ assert_equal(1, test.foo)
13
+ assert_equal(2, test.bar)
14
+ assert_equal(1, test[0])
15
+ assert_equal(2, test[1])
16
+
17
+ a, b = test.to_a
18
+ assert_equal(1, a)
19
+ assert_equal(2, b)
20
+
21
+ test[0] = 22
22
+ assert_equal(22, test.foo)
23
+
24
+ test.bar = 47
25
+ assert_equal(47, test.bar)
26
+ end
27
+
28
+ # [ruby-dev:26247] more than 10 struct members causes segmentation fault
29
+ def test_morethan10members
30
+ list = %w( a b c d e f g h i j k l m n o p )
31
+ until list.empty?
32
+ c = Struct.new(* list.map {|ch| ch.intern }).new
33
+ list.each do |ch|
34
+ c.__send__(ch)
35
+ end
36
+ list.pop
37
+ end
38
+ end
39
+
40
+ def test_small_structs
41
+ names = [:a, :b, :c, :d]
42
+ 1.upto(4) {|n|
43
+ fields = names[0, n]
44
+ klass = Struct.new(*fields)
45
+ o = klass.new(*(0...n).to_a)
46
+ fields.each_with_index {|name, i|
47
+ assert_equal(i, o[name])
48
+ }
49
+ o = klass.new(*(0...n).to_a.reverse)
50
+ fields.each_with_index {|name, i|
51
+ assert_equal(n-i-1, o[name])
52
+ }
53
+ }
54
+ end
55
+
56
+ def test_inherit
57
+ klass = Struct.new(:a)
58
+ klass2 = Class.new(klass)
59
+ o = klass2.new(1)
60
+ assert_equal(1, o.a)
61
+ end
62
+
63
+ def test_members
64
+ klass = Struct.new(:a)
65
+ o = klass.new(1)
66
+ assert_equal([:a], klass.members)
67
+ assert_equal([:a], o.members)
68
+ end
69
+
70
+ def test_ref
71
+ klass = Struct.new(:a)
72
+ o = klass.new(1)
73
+ assert_equal(1, o[:a])
74
+ assert_raise(NameError) { o[:b] }
75
+ end
76
+
77
+ def test_modify
78
+ klass = Struct.new(:a)
79
+ o = klass.new(1)
80
+ assert_raise(SecurityError) do
81
+ Thread.new do
82
+ $SAFE = 4
83
+ o.a = 2
84
+ end.value
85
+ end
86
+ end
87
+
88
+ def test_set
89
+ klass = Struct.new(:a)
90
+ o = klass.new(1)
91
+ o[:a] = 2
92
+ assert_equal(2, o[:a])
93
+ assert_raise(NameError) { o[:b] = 3 }
94
+ end
95
+
96
+ def test_struct_new
97
+ assert_raise(NameError) { Struct.new("foo") }
98
+ assert_nothing_raised { Struct.new("Foo") }
99
+ Struct.instance_eval { remove_const(:Foo) }
100
+ assert_nothing_raised { Struct.new(:a) { } }
101
+ assert_raise(RuntimeError) { Struct.new(:a) { raise } }
102
+
103
+ assert_equal([:utime, :stime, :cutime, :cstime], Process.times.members)
104
+ end
105
+
106
+ def test_initialize
107
+ klass = Struct.new(:a)
108
+ assert_raise(ArgumentError) { klass.new(1, 2) }
109
+ end
110
+
111
+ def test_each
112
+ klass = Struct.new(:a, :b)
113
+ o = klass.new(1, 2)
114
+ assert_equal([1, 2], o.each.to_a)
115
+ end
116
+
117
+ def test_each_pair
118
+ klass = Struct.new(:a, :b)
119
+ o = klass.new(1, 2)
120
+ assert_equal([[:a, 1], [:b, 2]], o.each_pair.to_a)
121
+ bug7382 = '[ruby-dev:46533]'
122
+ a = []
123
+ o.each_pair {|x| a << x}
124
+ assert_equal([[:a, 1], [:b, 2]], a, bug7382)
125
+ end
126
+
127
+ def test_inspect
128
+ klass = Struct.new(:a)
129
+ o = klass.new(1)
130
+ assert_equal("#<struct a=1>", o.inspect)
131
+ o.a = o
132
+ assert_match(/^#<struct a=#<struct #<.*?>:...>>$/, o.inspect)
133
+
134
+ Struct.new("Foo", :a)
135
+ o = Struct::Foo.new(1)
136
+ assert_equal("#<struct Struct::Foo a=1>", o.inspect)
137
+ Struct.instance_eval { remove_const(:Foo) }
138
+
139
+ klass = Struct.new(:a, :b)
140
+ o = klass.new(1, 2)
141
+ assert_equal("#<struct a=1, b=2>", o.inspect)
142
+
143
+ klass = Struct.new(:@a)
144
+ o = klass.new(1)
145
+ assert_equal("#<struct :@a=1>", o.inspect)
146
+ end
147
+
148
+ def test_init_copy
149
+ klass = Struct.new(:a)
150
+ o = klass.new(1)
151
+ assert_equal(o, o.dup)
152
+ end
153
+
154
+ def test_aref
155
+ klass = Struct.new(:a)
156
+ o = klass.new(1)
157
+ assert_equal(1, o[0])
158
+ assert_raise(IndexError) { o[-2] }
159
+ assert_raise(IndexError) { o[1] }
160
+ end
161
+
162
+ def test_aset
163
+ klass = Struct.new(:a)
164
+ o = klass.new(1)
165
+ o[0] = 2
166
+ assert_equal(2, o[:a])
167
+ assert_raise(IndexError) { o[-2] = 3 }
168
+ assert_raise(IndexError) { o[1] = 3 }
169
+ end
170
+
171
+ def test_values_at
172
+ klass = Struct.new(:a, :b, :c, :d, :e, :f)
173
+ o = klass.new(1, 2, 3, 4, 5, 6)
174
+ assert_equal([2, 4, 6], o.values_at(1, 3, 5))
175
+ assert_equal([2, 3, 4, 3, 4, 5], o.values_at(1..3, 2...5))
176
+ end
177
+
178
+ def test_select
179
+ klass = Struct.new(:a, :b, :c, :d, :e, :f)
180
+ o = klass.new(1, 2, 3, 4, 5, 6)
181
+ assert_equal([1, 3, 5], o.select {|v| v % 2 != 0 })
182
+ assert_raise(ArgumentError) { o.select(1) }
183
+ end
184
+
185
+ def test_equal
186
+ klass1 = Struct.new(:a)
187
+ klass2 = Struct.new(:a, :b)
188
+ o1 = klass1.new(1)
189
+ o2 = klass1.new(1)
190
+ o3 = klass2.new(1)
191
+ assert(o1.==(o2))
192
+ assert(o1 != o3)
193
+ end
194
+
195
+ def test_hash
196
+ klass = Struct.new(:a)
197
+ o = klass.new(1)
198
+ assert(o.hash.is_a?(Fixnum))
199
+ end
200
+
201
+ def test_eql
202
+ klass1 = Struct.new(:a)
203
+ klass2 = Struct.new(:a, :b)
204
+ o1 = klass1.new(1)
205
+ o2 = klass1.new(1)
206
+ o3 = klass2.new(1)
207
+ assert(o1.eql?(o2))
208
+ assert(!(o1.eql?(o3)))
209
+ end
210
+
211
+ def test_size
212
+ klass = Struct.new(:a)
213
+ o = klass.new(1)
214
+ assert_equal(1, o.size)
215
+ end
216
+
217
+ def test_error
218
+ assert_raise(TypeError){
219
+ Struct.new(0)
220
+ }
221
+ end
222
+
223
+ def test_nonascii
224
+ struct_test = Struct.new("R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}")
225
+ assert_equal(Struct.const_get("R\u{e9}sum\u{e9}"), struct_test, '[ruby-core:24849]')
226
+ a = struct_test.new(42)
227
+ assert_equal("#<struct Struct::R\u{e9}sum\u{e9} r\u{e9}sum\u{e9}=42>", a.inspect, '[ruby-core:24849]')
228
+ end
229
+
230
+ def test_junk
231
+ struct_test = Struct.new("Foo", "a\000")
232
+ o = struct_test.new(1)
233
+ assert_equal(1, o.send("a\000"))
234
+ Struct.instance_eval { remove_const(:Foo) }
235
+ end
236
+
237
+ def test_comparison_when_recursive
238
+ klass1 = Struct.new(:a, :b, :c)
239
+
240
+ x = klass1.new(1, 2, nil); x.c = x
241
+ y = klass1.new(1, 2, nil); y.c = y
242
+ Timeout.timeout(1) {
243
+ assert x == y
244
+ assert x.eql? y
245
+ }
246
+
247
+ z = klass1.new(:something, :other, nil); z.c = z
248
+ Timeout.timeout(1) {
249
+ assert x != z
250
+ assert !x.eql?(z)
251
+ }
252
+
253
+ x.c = y; y.c = x
254
+ Timeout.timeout(1) {
255
+ assert x == y
256
+ assert x.eql?(y)
257
+ }
258
+
259
+ x.c = z; z.c = x
260
+ Timeout.timeout(1) {
261
+ assert x != z
262
+ assert !x.eql?(z)
263
+ }
264
+ end
265
+
266
+ def test_struct_subclass
267
+ bug5036 = '[ruby-dev:44122]'
268
+ st = Class.new(Struct)
269
+ s = st.new("S", :m).new
270
+ error = assert_raise(SecurityError) do
271
+ proc do
272
+ $SAFE = 4
273
+ s.m = 1
274
+ end.call
275
+ end
276
+ assert_equal("Insecure: can't modify #{st}::S", error.message, bug5036)
277
+ end
278
+
279
+ def test_to_h
280
+ klass = Struct.new(:a, :b, :c, :d, :e, :f)
281
+ o = klass.new(1, 2, 3, 4, 5, 6)
282
+ assert_equal({a:1, b:2, c:3, d:4, e:5, f:6}, o.to_h)
283
+ end
284
+ end
data/test/run.sh ADDED
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+
3
+ bundle exec bacon -rsimplecov -I lib test/spec_*.rb
4
+ BACON=$?
5
+
6
+ bundle exec ruby -I lib test/compatibility-test.rb
7
+ COMPAT=$?
8
+
9
+ if [ ${BACON} -ne 0 ] || [ ${COMPAT} -ne 0 ]
10
+ then
11
+ exit 1
12
+ fi
@@ -0,0 +1,193 @@
1
+ require "structx"
2
+
3
+ class A < StructX
4
+ member :x
5
+ member :y, default: 10
6
+ member :z, type: Integer, default: 100
7
+ end
8
+
9
+ describe "StructX" do
10
+ describe "StructX.new(:x, :y, :z)" do
11
+ before do
12
+ @class = StructX.new(:x, :y, :z)
13
+ end
14
+
15
+ it "should have 3 members" do
16
+ @class.members.size.should == 3
17
+ end
18
+
19
+ it "should create from StructX subclass" do
20
+ should.not.raise do
21
+ Class.new(StructX).new(:x).new(1)
22
+ end
23
+ end
24
+
25
+ it "should inherit members" do
26
+ Class.new(@class).members.should == [:x, :y, :z]
27
+ end
28
+
29
+ it "should create an instance" do
30
+ @class.new(1, 2, 3).tap do |obj|
31
+ obj.x.should == 1
32
+ obj.y.should == 2
33
+ obj.z.should == 3
34
+ end
35
+ end
36
+
37
+ it "should create an instance with key" do
38
+ @class.new(x: 1, y: 2, z: 3).tap do |obj|
39
+ obj.x.should == 1
40
+ obj.y.should == 2
41
+ obj.z.should == 3
42
+ end
43
+ end
44
+
45
+ it "should get members" do
46
+ @class.members.tap do |m|
47
+ m.should.include(:x)
48
+ m.should.include(:y)
49
+ m.should.include(:z)
50
+ end
51
+ end
52
+
53
+ it "should raise ArgumentError when number of values are greater than number of members" do
54
+ should.raise(ArgumentError) do
55
+ @class.new(1, 2, 3, 4)
56
+ end
57
+ end
58
+
59
+ it "should create an instance with #[]" do
60
+ @class[1, 2, 3].tap do |obj|
61
+ obj.x.should == 1
62
+ obj.y.should == 2
63
+ obj.z.should == 3
64
+ end
65
+ end
66
+
67
+ it "should equal" do
68
+ @class.new(1, 2, 3).should == @class.new(1, 2, 3)
69
+ end
70
+
71
+ it "should write and get member's value" do
72
+ @class.new(1, 2, 3).tap do |obj|
73
+ obj.x = 2
74
+ obj.y = 3
75
+ obj.z = 4
76
+ obj.x.should == 2
77
+ obj.y.should == 3
78
+ obj.z.should == 4
79
+ end
80
+ end
81
+
82
+ it "should get member's value with index" do
83
+ @class.new(1, 2, 3).tap do |x|
84
+ x[0].should == 1
85
+ x[1].should == 2
86
+ x[2].should == 3
87
+ should.raise(IndexError) { x[-4] }
88
+ should.raise(IndexError) { x[3] }
89
+ x[:x].should == 1
90
+ x[:y].should == 2
91
+ x[:z].should == 3
92
+ should.raise(NameError) { x[:a] }
93
+ end
94
+ end
95
+
96
+ it "should set member's value with index" do
97
+ @class.new(1, 2, 3).tap do |x|
98
+ x[0] = 2
99
+ x[1] = 3
100
+ x[2] = 4
101
+ x[0].should == 2
102
+ x[1].should == 3
103
+ x[2].should == 4
104
+ should.raise(IndexError) { x[-4] = 1 }
105
+ should.raise(IndexError) { x[3] = 1 }
106
+ x[:x] = 3
107
+ x[:y] = 4
108
+ x[:z] = 5
109
+ x[:x].should == 3
110
+ x[:y].should == 4
111
+ x[:z].should == 5
112
+ should.raise(NameError) { x[:a] = 1}
113
+ end
114
+ end
115
+
116
+ it "should iterate values" do
117
+ vals = []
118
+ @class.new(1, 2, 3).tap{|x| x.each {|val| vals << val}; vals.should == x.values}
119
+ end
120
+
121
+ it "should iterate pairs of key and value" do
122
+ vals = []
123
+ @class.new(1, 2, 3).tap{|x| x.each_pair {|k, v| vals << [k, v]}; vals.should == x.to_h.to_a}
124
+ end
125
+
126
+ it "should get size" do
127
+ @class.new(1, 2, 3).size.should == 3
128
+ end
129
+
130
+ it "should get members as strings" do
131
+ @class.new.members.should == [:x, :y, :z]
132
+ end
133
+
134
+ it "should select" do
135
+ @class.new(1, 2, 3).select{|i| i.odd?}.should == [1, 3]
136
+ end
137
+
138
+ it "should get values" do
139
+ @class.new(1, 2, 3).values.should == [1, 2, 3]
140
+ end
141
+
142
+ it "should get values at" do
143
+ @class.new(1, 2, 3).values_at(0..1).should == [1, 2]
144
+ end
145
+ end
146
+
147
+ StructX.new("TestName", :x, :y)
148
+
149
+ describe 'StructX.new("TestName", :x, :y)' do
150
+ it "should have 2 members" do
151
+ StructX::TestName.members.size.should == 2
152
+ end
153
+
154
+ it "should create class" do
155
+ should.not.raise {StructX::TestName}
156
+ end
157
+
158
+ it "should get values" do
159
+ StructX::TestName.new(1, 2).tap do |obj|
160
+ obj.x.should == 1
161
+ obj.y.should == 2
162
+ end
163
+ end
164
+ end
165
+
166
+ describe "A < StructX" do
167
+ it "should have 3 members" do
168
+ A.members.size.should == 3
169
+ end
170
+
171
+ it "should get members" do
172
+ A.new(x: 1, y: 2, z: 3).tap do |obj|
173
+ obj.x.should == 1
174
+ obj.y.should == 2
175
+ obj.z.should == 3
176
+ end
177
+ end
178
+
179
+ it "should get default value" do
180
+ A.new(1).tap do |obj|
181
+ obj.x.should == 1
182
+ obj.y.should == 10
183
+ obj.z.should == 100
184
+ end
185
+ A.new.tap do |obj|
186
+ obj.x.should == nil
187
+ obj.y.should == 10
188
+ obj.z.should == 100
189
+ end
190
+ end
191
+ end
192
+ end
193
+