blockenspiel 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.
data/tests/tc_basic.rb ADDED
@@ -0,0 +1,135 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Blockenspiel basic tests
4
+ #
5
+ # This file contains tests for the simple use cases.
6
+ #
7
+ # -----------------------------------------------------------------------------
8
+ # Copyright 2008 Daniel Azuma
9
+ #
10
+ # All rights reserved.
11
+ #
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions are met:
14
+ #
15
+ # * Redistributions of source code must retain the above copyright notice,
16
+ # this list of conditions and the following disclaimer.
17
+ # * Redistributions in binary form must reproduce the above copyright notice,
18
+ # this list of conditions and the following disclaimer in the documentation
19
+ # and/or other materials provided with the distribution.
20
+ # * Neither the name of the copyright holder, nor the names of any other
21
+ # contributors to this software, may be used to endorse or promote products
22
+ # derived from this software without specific prior written permission.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ # POSSIBILITY OF SUCH DAMAGE.
35
+ # -----------------------------------------------------------------------------
36
+
37
+
38
+ require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
39
+
40
+
41
+ module Blockenspiel
42
+ module Tests # :nodoc:
43
+
44
+ class TestBasic < Test::Unit::TestCase # :nodoc:
45
+
46
+
47
+ class SimpleTarget < Blockenspiel::Base
48
+
49
+ def initialize
50
+ @hash = Hash.new
51
+ end
52
+
53
+ def set_value(key_, value_)
54
+ @hash[key_] = value_
55
+ end
56
+
57
+ def set_value_by_block(key_)
58
+ @hash[key_] = yield
59
+ end
60
+
61
+ def get_value(key_)
62
+ @hash[key_]
63
+ end
64
+ dsl_method :get_value, false
65
+
66
+ end
67
+
68
+
69
+ # Test basic usage with a parameter object.
70
+ #
71
+ # * Asserts that methods are not mixed in to self.
72
+ # * Asserts that the specified target object does in fact receive the block messages.
73
+
74
+ def test_basic_param
75
+ block_ = proc do |t_|
76
+ t_.set_value(:a, 1)
77
+ t_.set_value_by_block(:b){ 2 }
78
+ assert(!self.respond_to?(:set_value))
79
+ assert(!self.respond_to?(:set_value_by_block))
80
+ end
81
+ target_ = SimpleTarget.new
82
+ Blockenspiel.invoke(block_, target_)
83
+ assert_equal(1, target_.get_value(:a))
84
+ assert_equal(2, target_.get_value(:b))
85
+ end
86
+
87
+
88
+ # Test basic usage with a mixin.
89
+ #
90
+ # * Asserts that methods are mixed in to self.
91
+ # * Asserts that methods are removed from self afterward.
92
+ # * Asserts that the specified target object still receives the messages.
93
+
94
+ def test_basic_mixin
95
+ block_ = proc do
96
+ set_value(:a, 1)
97
+ set_value_by_block(:b){ 2 }
98
+ end
99
+ target_ = SimpleTarget.new
100
+ Blockenspiel.invoke(block_, target_)
101
+ assert(!self.respond_to?(:set_value))
102
+ assert(!self.respond_to?(:set_value_by_block))
103
+ assert_equal(1, target_.get_value(:a))
104
+ assert_equal(2, target_.get_value(:b))
105
+ end
106
+
107
+
108
+ # Test basic usage with a builder.
109
+ #
110
+ # * Asserts that the receivers are called.
111
+ # * Asserts that receivers with blocks are handled properly.
112
+
113
+ def test_basic_builder
114
+ block_ = proc do
115
+ set_value(:a, 1)
116
+ set_value_by_block(:b){ 2 }
117
+ end
118
+ hash_ = Hash.new
119
+ Blockenspiel.invoke(block_) do
120
+ add_method(:set_value) do |key_, value_|
121
+ hash_[key_] = value_
122
+ end
123
+ add_method(:set_value_by_block, :receive_block => true) do |key_, bl_|
124
+ hash_[key_] = bl_.call
125
+ end
126
+ end
127
+ assert_equal(1, hash_[:a])
128
+ assert_equal(2, hash_[:b])
129
+ end
130
+
131
+
132
+ end
133
+
134
+ end
135
+ end
@@ -0,0 +1,283 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Blockenspiel dsl method tests
4
+ #
5
+ # This file contains tests for the dsl method directives.
6
+ #
7
+ # -----------------------------------------------------------------------------
8
+ # Copyright 2008 Daniel Azuma
9
+ #
10
+ # All rights reserved.
11
+ #
12
+ # Redistribution and use in source and binary forms, with or without
13
+ # modification, are permitted provided that the following conditions are met:
14
+ #
15
+ # * Redistributions of source code must retain the above copyright notice,
16
+ # this list of conditions and the following disclaimer.
17
+ # * Redistributions in binary form must reproduce the above copyright notice,
18
+ # this list of conditions and the following disclaimer in the documentation
19
+ # and/or other materials provided with the distribution.
20
+ # * Neither the name of the copyright holder, nor the names of any other
21
+ # contributors to this software, may be used to endorse or promote products
22
+ # derived from this software without specific prior written permission.
23
+ #
24
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
+ # POSSIBILITY OF SUCH DAMAGE.
35
+ # -----------------------------------------------------------------------------
36
+
37
+
38
+ require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
39
+
40
+
41
+ module Blockenspiel
42
+ module Tests # :nodoc:
43
+
44
+ class TestDSLMethods < Test::Unit::TestCase # :nodoc:
45
+
46
+
47
+ class Target1 < Blockenspiel::Base
48
+
49
+ def initialize(hash_)
50
+ @hash = hash_
51
+ end
52
+
53
+ def set_value1(key_, value_)
54
+ @hash["#{key_}1"] = value_
55
+ end
56
+
57
+ def set_value2(key_)
58
+ @hash["#{key_}2"] = yield
59
+ end
60
+
61
+ def _set_value3(key_, value_)
62
+ @hash["#{key_}3"] = value_
63
+ end
64
+
65
+ end
66
+
67
+
68
+ class Target2 < Blockenspiel::Base
69
+
70
+ def initialize(hash_)
71
+ @hash = hash_
72
+ end
73
+
74
+ dsl_methods false
75
+
76
+ def set_value1(key_, value_)
77
+ @hash["#{key_}1"] = value_
78
+ end
79
+
80
+ dsl_methods true
81
+
82
+ def set_value2(key_)
83
+ @hash["#{key_}2"] = yield
84
+ end
85
+
86
+ def _set_value3(key_, value_)
87
+ @hash["#{key_}3"] = value_
88
+ end
89
+
90
+ end
91
+
92
+
93
+ class Target3 < Blockenspiel::Base
94
+
95
+ def initialize(hash_)
96
+ @hash = hash_
97
+ end
98
+
99
+ dsl_methods false
100
+
101
+ def set_value1(key_, value_)
102
+ @hash["#{key_}1"] = value_
103
+ end
104
+ dsl_method :set_value1
105
+
106
+ def set_value2(key_)
107
+ @hash["#{key_}2"] = yield
108
+ end
109
+ dsl_method :renamed_set_value2, :set_value2
110
+ dsl_method :another_set_value2, :set_value2
111
+
112
+ end
113
+
114
+
115
+ class Target4 < Blockenspiel::Base
116
+
117
+ def initialize(hash_)
118
+ @hash = hash_
119
+ end
120
+
121
+ def set_value1(key_, value_)
122
+ @hash["#{key_}1"] = value_
123
+ end
124
+ dsl_method :set_value1, false
125
+
126
+ def set_value2(key_)
127
+ @hash["#{key_}2"] = yield
128
+ end
129
+ dsl_method :set_value2, false
130
+ dsl_method :renamed_set_value2, :set_value2
131
+
132
+ end
133
+
134
+
135
+ class Target5a < Blockenspiel::Base
136
+
137
+ def initialize(hash_)
138
+ @hash = hash_
139
+ end
140
+
141
+ def set_value1(key_, value_)
142
+ @hash["#{key_}1"] = value_
143
+ end
144
+
145
+ def set_value2(key_)
146
+ @hash["#{key_}2"] = yield
147
+ end
148
+
149
+ def set_value3(key_, value_)
150
+ @hash["#{key_}3"] = value_
151
+ end
152
+
153
+ def set_value4(key_, value_)
154
+ @hash["#{key_}4"] = value_
155
+ end
156
+ dsl_method :set_value4, false
157
+ dsl_method :renamed_set_value4, :set_value4
158
+
159
+ end
160
+
161
+
162
+ class Target5b < Target5a
163
+
164
+ def set_value1(key_, value_)
165
+ @hash["#{key_}1sub"] = value_
166
+ end
167
+
168
+ dsl_method :set_value3, false
169
+
170
+ def set_value5(key_, value_)
171
+ @hash["#{key_}5"] = value_
172
+ end
173
+
174
+ end
175
+
176
+
177
+ # Test default dsl method setting.
178
+ #
179
+ # * Asserts the right dsl methods are added for the default setting.
180
+
181
+ def test_default_setting
182
+ hash_ = Hash.new
183
+ block_ = proc do
184
+ set_value1('a', 1)
185
+ set_value2('b'){ 2 }
186
+ assert_raise(NoMethodError){ _set_value3('c', 3) }
187
+ end
188
+ Blockenspiel.invoke(block_, Target1.new(hash_))
189
+ assert_equal(1, hash_['a1'])
190
+ assert_equal(2, hash_['b2'])
191
+ assert_nil(hash_['c3'])
192
+ end
193
+
194
+
195
+ # Test dsl_methods true and false switching.
196
+ #
197
+ # * Asserts that dsl_methods false turns off automatic method creation.
198
+ # * Asserts that dsl_methods true turns on automatic method creation.
199
+ # * Asserts that underscore methods are added in dsl_methods true mode.
200
+
201
+ def test_onoff_switching
202
+ hash_ = Hash.new
203
+ block_ = proc do
204
+ assert_raise(NoMethodError){ _set_value1('a', 1) }
205
+ set_value2('b'){ 2 }
206
+ _set_value3('c', 3)
207
+ end
208
+ Blockenspiel.invoke(block_, Target2.new(hash_))
209
+ assert_nil(hash_['a1'])
210
+ assert_equal(2, hash_['b2'])
211
+ assert_equal(3, hash_['c3'])
212
+ end
213
+
214
+
215
+ # Test dsl_methods explicit adding.
216
+ #
217
+ # * Asserts that adding an explicit dsl method works.
218
+ # * Asserts that adding an explicit dsl method with a different name works.
219
+
220
+ def test_explicit_add
221
+ hash_ = Hash.new
222
+ block_ = proc do
223
+ set_value1('a', 1)
224
+ assert_raise(NoMethodError){ set_value2('b'){ 2 } }
225
+ renamed_set_value2('c'){ 3 }
226
+ another_set_value2('d'){ 4 }
227
+ end
228
+ Blockenspiel.invoke(block_, Target3.new(hash_))
229
+ assert_equal(1, hash_['a1'])
230
+ assert_nil(hash_['b2'])
231
+ assert_equal(3, hash_['c2'])
232
+ assert_equal(4, hash_['d2'])
233
+ end
234
+
235
+
236
+ # Test dsl_methods explicit removing.
237
+ #
238
+ # * Asserts that removing a dsl method works.
239
+ # * Asserts that re-adding a removed method with a different name works.
240
+
241
+ def test_explicit_removing
242
+ hash_ = Hash.new
243
+ block_ = proc do
244
+ assert_raise(NoMethodError){ set_value1('a', 1) }
245
+ assert_raise(NoMethodError){ set_value2('b'){ 2 } }
246
+ renamed_set_value2('c'){ 3 }
247
+ end
248
+ Blockenspiel.invoke(block_, Target4.new(hash_))
249
+ assert_nil(hash_['a1'])
250
+ assert_nil(hash_['b2'])
251
+ assert_equal(3, hash_['c2'])
252
+ end
253
+
254
+
255
+ # Test dsl method setting with subclasses
256
+ #
257
+ # * Asserts that modules are properly inherited.
258
+ # * Asserts that method overriding is done correctly.
259
+
260
+ def test_subclassing
261
+ hash_ = Hash.new
262
+ block_ = proc do
263
+ set_value1('a', 1)
264
+ set_value2('b'){ 2 }
265
+ assert_raise(NoMethodError){ set_value3('c', 3) }
266
+ assert_raise(NoMethodError){ set_value4('d', 4) }
267
+ renamed_set_value4('e', 5)
268
+ set_value5('f', 6)
269
+ end
270
+ Blockenspiel.invoke(block_, Target5b.new(hash_))
271
+ assert_equal(1, hash_['a1sub'])
272
+ assert_equal(2, hash_['b2'])
273
+ assert_nil(hash_['c3'])
274
+ assert_nil(hash_['d4'])
275
+ assert_equal(5, hash_['e4'])
276
+ assert_equal(6, hash_['f5'])
277
+ end
278
+
279
+
280
+ end
281
+
282
+ end
283
+ end
@@ -0,0 +1,206 @@
1
+ # -----------------------------------------------------------------------------
2
+ #
3
+ # Blockenspiel mixin tests
4
+ #
5
+ # This file contains tests for various mixin cases,
6
+ # including nested blocks and multithreading.
7
+ #
8
+ # -----------------------------------------------------------------------------
9
+ # Copyright 2008 Daniel Azuma
10
+ #
11
+ # All rights reserved.
12
+ #
13
+ # Redistribution and use in source and binary forms, with or without
14
+ # modification, are permitted provided that the following conditions are met:
15
+ #
16
+ # * Redistributions of source code must retain the above copyright notice,
17
+ # this list of conditions and the following disclaimer.
18
+ # * Redistributions in binary form must reproduce the above copyright notice,
19
+ # this list of conditions and the following disclaimer in the documentation
20
+ # and/or other materials provided with the distribution.
21
+ # * Neither the name of the copyright holder, nor the names of any other
22
+ # contributors to this software, may be used to endorse or promote products
23
+ # derived from this software without specific prior written permission.
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
+ # POSSIBILITY OF SUCH DAMAGE.
36
+ # -----------------------------------------------------------------------------
37
+
38
+
39
+ require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
40
+
41
+
42
+ module Blockenspiel
43
+ module Tests # :nodoc:
44
+
45
+ class TestMixins < Test::Unit::TestCase # :nodoc:
46
+
47
+
48
+ class Target1 < Blockenspiel::Base
49
+
50
+ def initialize(hash_)
51
+ @hash = hash_
52
+ end
53
+
54
+ def set_value(key_, value_)
55
+ @hash["#{key_}1"] = value_
56
+ end
57
+
58
+ def set_value2(key_)
59
+ @hash["#{key_}1"] = yield
60
+ end
61
+
62
+ end
63
+
64
+
65
+ class Target2 < Blockenspiel::Base
66
+
67
+ dsl_methods false
68
+
69
+ def initialize(hash_=nil)
70
+ @hash = hash_ || Hash.new
71
+ end
72
+
73
+ def set_value(key_, value_)
74
+ @hash["#{key_}2"] = value_
75
+ end
76
+ dsl_method :set_value
77
+
78
+ def set_value2(key_)
79
+ @hash["#{key_}2"] = yield
80
+ end
81
+ dsl_method :set_value2_inmixin, :set_value2
82
+
83
+ end
84
+
85
+
86
+ # Basic test of mixin mechanism.
87
+ #
88
+ # * Asserts that the mixin methods are added and removed for a single mixin.
89
+ # * Asserts that the methods properly delegate to the target object.
90
+ # * Asserts that self doesn't change, and instance variables are preserved.
91
+
92
+ def test_basic_mixin
93
+ hash_ = Hash.new
94
+ saved_object_id_ = self.object_id
95
+ @my_instance_variable_test = :hello
96
+ assert(!self.respond_to?(:set_value))
97
+ assert(!self.respond_to?(:set_value2))
98
+ block_ = proc do
99
+ set_value('a', 1)
100
+ set_value2('b'){ 2 }
101
+ assert_equal(:hello, @my_instance_variable_test)
102
+ assert_equal(saved_object_id_, self.object_id)
103
+ end
104
+ Blockenspiel.invoke(block_, Target1.new(hash_))
105
+ assert(!self.respond_to?(:set_value))
106
+ assert(!self.respond_to?(:set_value2))
107
+ assert_equal(1, hash_['a1'])
108
+ assert_equal(2, hash_['b1'])
109
+ end
110
+
111
+
112
+ # Test renaming of mixin methods.
113
+ #
114
+ # * Asserts that correctly renamed mixin methods are added and removed.
115
+ # * Asserts that the methods properly delegate to the target object.
116
+
117
+ def test_mixin_with_renaming
118
+ hash_ = Hash.new
119
+ assert(!self.respond_to?(:set_value))
120
+ assert(!self.respond_to?(:set_value2))
121
+ assert(!self.respond_to?(:set_value2_inmixin))
122
+ block_ = proc do
123
+ set_value('a', 1)
124
+ set_value2_inmixin('b'){ 2 }
125
+ assert(!self.respond_to?(:set_value2))
126
+ end
127
+ Blockenspiel.invoke(block_, Target2.new(hash_))
128
+ assert(!self.respond_to?(:set_value))
129
+ assert(!self.respond_to?(:set_value2))
130
+ assert(!self.respond_to?(:set_value2_inmixin))
131
+ assert_equal(1, hash_['a2'])
132
+ assert_equal(2, hash_['b2'])
133
+ end
134
+
135
+
136
+ # Test of two different nested mixins.
137
+ #
138
+ # * Asserts that the right methods are added and removed at the right time.
139
+ # * Asserts that the methods delegate to the right target object, even when
140
+ # multiple mixins add the same method name
141
+
142
+ def test_nested_different
143
+ hash_ = Hash.new
144
+ assert(!self.respond_to?(:set_value))
145
+ assert(!self.respond_to?(:set_value2))
146
+ assert(!self.respond_to?(:set_value2_inmixin))
147
+ Blockenspiel.invoke(proc do
148
+ set_value('a', 1)
149
+ set_value2('b'){ 2 }
150
+ assert(!self.respond_to?(:set_value2_inmixin))
151
+ Blockenspiel.invoke(proc do
152
+ set_value('c', 1)
153
+ set_value2_inmixin('d'){ 2 }
154
+ end, Target2.new(hash_))
155
+ assert(!self.respond_to?(:set_value2_inmixin))
156
+ set_value('e', 1)
157
+ set_value2('f'){ 2 }
158
+ end, Target1.new(hash_))
159
+ assert(!self.respond_to?(:set_value))
160
+ assert(!self.respond_to?(:set_value2))
161
+ assert(!self.respond_to?(:set_value2_inmixin))
162
+ assert_equal(1, hash_['a1'])
163
+ assert_equal(2, hash_['b1'])
164
+ assert_equal(1, hash_['c2'])
165
+ assert_equal(2, hash_['d2'])
166
+ assert_equal(1, hash_['e1'])
167
+ assert_equal(2, hash_['f1'])
168
+ end
169
+
170
+
171
+ # Test of the same mixin nested in itself.
172
+ #
173
+ # * Asserts that the methods are added and removed at the right time.
174
+
175
+ def test_nested_same
176
+ hash_ = Hash.new
177
+ assert(!self.respond_to?(:set_value))
178
+ assert(!self.respond_to?(:set_value2))
179
+ assert(!self.respond_to?(:set_value2_inmixin))
180
+ Blockenspiel.invoke(proc do
181
+ set_value('a', 1)
182
+ set_value2_inmixin('b'){ 2 }
183
+ Blockenspiel.invoke(proc do
184
+ set_value('c', 1)
185
+ set_value2_inmixin('d'){ 2 }
186
+ assert(!self.respond_to?(:set_value2))
187
+ end, Target2.new(hash_))
188
+ set_value('e', 1)
189
+ set_value2_inmixin('f'){ 2 }
190
+ end, Target2.new(hash_))
191
+ assert(!self.respond_to?(:set_value))
192
+ assert(!self.respond_to?(:set_value2))
193
+ assert(!self.respond_to?(:set_value2_inmixin))
194
+ assert_equal(1, hash_['a2'])
195
+ assert_equal(2, hash_['b2'])
196
+ assert_equal(1, hash_['c2'])
197
+ assert_equal(2, hash_['d2'])
198
+ assert_equal(1, hash_['e2'])
199
+ assert_equal(2, hash_['f2'])
200
+ end
201
+
202
+
203
+ end
204
+
205
+ end
206
+ end