structx 0.1.0

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,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
+