gorillib 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +3 -0
  2. data/.gitmodules +3 -0
  3. data/.travis.yml +11 -0
  4. data/Gemfile +2 -16
  5. data/Rakefile +2 -74
  6. data/away/aliasing_spec.rb +180 -0
  7. data/away/confidence.rb +17 -0
  8. data/away/stub_module.rb +33 -0
  9. data/gorillib.gemspec +31 -246
  10. data/lib/gorillib/collection/model_collection.rb +1 -0
  11. data/lib/gorillib/data_munging.rb +0 -1
  12. data/lib/gorillib/hashlike/slice.rb +2 -0
  13. data/lib/gorillib/model/field.rb +2 -2
  14. data/lib/gorillib/model/serialization.rb +9 -4
  15. data/lib/gorillib/model/serialization/csv.rb +1 -0
  16. data/lib/gorillib/model/serialization/lines.rb +2 -0
  17. data/lib/gorillib/model/serialization/tsv.rb +1 -0
  18. data/lib/gorillib/pathname.rb +1 -1
  19. data/lib/gorillib/pathname/utils.rb +6 -0
  20. data/lib/gorillib/string/inflector.rb +1 -1
  21. data/lib/gorillib/system.rb +1 -0
  22. data/lib/gorillib/system/runner.rb +36 -0
  23. data/lib/gorillib/type/ip_address.rb +2 -2
  24. data/lib/gorillib/version.rb +3 -0
  25. data/old/lib/gorillib/hash/indifferent_access.rb +207 -0
  26. data/old/lib/gorillib/hash/tree_merge.rb +4 -0
  27. data/old/lib/gorillib/hashlike/tree_merge.rb +49 -0
  28. data/old/lib/gorillib/metaprogramming/cattr_accessor.rb +79 -0
  29. data/old/lib/gorillib/metaprogramming/mattr_accessor.rb +61 -0
  30. data/old/lib/gorillib/receiver.rb +402 -0
  31. data/old/lib/gorillib/receiver/active_model_shim.rb +32 -0
  32. data/old/lib/gorillib/receiver/acts_as_hash.rb +195 -0
  33. data/old/lib/gorillib/receiver/acts_as_loadable.rb +42 -0
  34. data/old/lib/gorillib/receiver/locale/en.yml +27 -0
  35. data/old/lib/gorillib/receiver/tree_diff.rb +74 -0
  36. data/old/lib/gorillib/receiver/validations.rb +30 -0
  37. data/old/lib/gorillib/receiver_model.rb +21 -0
  38. data/old/lib/gorillib/struct/acts_as_hash.rb +108 -0
  39. data/old/lib/gorillib/struct/hashlike_iteration.rb +0 -0
  40. data/old/spec/gorillib/hash/indifferent_access_spec.rb +391 -0
  41. data/old/spec/gorillib/metaprogramming/cattr_accessor_spec.rb +43 -0
  42. data/old/spec/gorillib/metaprogramming/mattr_accessor_spec.rb +45 -0
  43. data/old/spec/gorillib/receiver/receiver/acts_as_hash_spec.rb +295 -0
  44. data/old/spec/gorillib/receiver_spec.rb +551 -0
  45. data/old/spec/gorillib/struct/acts_as_hash_fuzz_spec.rb +71 -0
  46. data/old/spec/gorillib/struct/acts_as_hash_spec.rb +422 -0
  47. data/spec/gorillib/array/compact_blank_spec.rb +2 -2
  48. data/spec/gorillib/collection_spec.rb +6 -6
  49. data/spec/gorillib/factories_spec.rb +2 -2
  50. data/spec/gorillib/hashlike_spec.rb +2 -1
  51. data/spec/gorillib/model/defaults_spec.rb +3 -3
  52. data/spec/gorillib/model/serialization/csv_spec.rb +35 -0
  53. data/spec/gorillib/model/serialization/tsv_spec.rb +20 -4
  54. data/spec/gorillib/model/serialization_spec.rb +3 -3
  55. data/spec/spec_helper.rb +6 -1
  56. data/spec/support/factory_test_helpers.rb +2 -2
  57. data/spec/support/gorillib_test_helpers.rb +4 -4
  58. data/spec/support/hashlike_fuzzing_helper.rb +1 -15
  59. data/spec/support/hashlike_helper.rb +5 -1
  60. data/spec/support/model_test_helpers.rb +12 -1
  61. metadata +192 -168
  62. data/notes/HOWTO.md +0 -22
  63. data/notes/bucket.md +0 -155
  64. data/notes/builder.md +0 -170
  65. data/notes/collection.md +0 -81
  66. data/notes/factories.md +0 -86
  67. data/notes/model-overlay.md +0 -209
  68. data/notes/model.md +0 -135
  69. data/notes/structured-data-classes.md +0 -127
@@ -0,0 +1,71 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ require 'gorillib/hashlike'
3
+ require 'gorillib/struct/acts_as_hash'
4
+ require 'gorillib/hash/indifferent_access'
5
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_fuzzing_helper')
6
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_helper')
7
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_struct_helper')
8
+
9
+ #
10
+ # Don't test the built-in Struct methods.
11
+ #
12
+ # Also, all the enumerable methods behave differently -- they build off each
13
+ # (which iterates like an array), not each_pair (which iterates like a hash)
14
+ #
15
+ STRUCT_HASHLIKE_METHODS_TO_SKIP = [:each, :flatten, :clear, :values_at] +
16
+ Enumerable.public_instance_methods.map(&:to_sym) +
17
+ HashlikeHelper::HASH_METHODS_MISSING_FROM_VERSION
18
+
19
+ describe Gorillib::Struct::ActsAsHash do
20
+ if ENV['FULL_SPECS']
21
+ include HashlikeFuzzingHelper
22
+
23
+ describe "vs Hash" do
24
+ before do
25
+ @total = 0
26
+ @hsh = HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT.dup
27
+ @hshlike = StructUsingHashlike.new.merge(HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT)
28
+ end
29
+
30
+ ( HashlikeHelper::METHODS_TO_TEST - STRUCT_HASHLIKE_METHODS_TO_SKIP ).each do |method_to_test|
31
+ describe "##{method_to_test}" do
32
+
33
+ (HashlikeFuzzingHelper::INPUTS_FOR_ALL_HASHLIKES).each do |input|
34
+ next if HashlikeFuzzingHelper::SPECIAL_CASES_FOR_HASHLIKE_STRUCT[method_to_test].include?(input)
35
+
36
+ it "on #{input.inspect}" do
37
+ behaves_the_same(@hsh, @hshlike, method_to_test, input)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "vs Gorillib::HashWithIndifferentSymbolKeys" do
45
+ before do
46
+ @total = 0
47
+ @hsh = Gorillib::HashWithIndifferentSymbolKeys.new_from_hash_copying_default(
48
+ HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT)
49
+ @hshlike = StructUsingHashlike.new.merge(
50
+ HashlikeHelper::HASH_TO_TEST_HASHLIKE_STRUCT)
51
+ end
52
+
53
+ ( HashlikeHelper::METHODS_TO_TEST - STRUCT_HASHLIKE_METHODS_TO_SKIP
54
+ ).each do |method_to_test|
55
+ describe "##{method_to_test}" do
56
+
57
+ ( HashlikeFuzzingHelper::INPUTS_WHEN_INDIFFERENT_ACCESS +
58
+ HashlikeFuzzingHelper::INPUTS_FOR_ALL_HASHLIKES
59
+ ).each do |input|
60
+ next if HashlikeFuzzingHelper::SPECIAL_CASES_FOR_HASHLIKE_STRUCT[method_to_test].include?(input)
61
+
62
+ it "on #{input.inspect}" do
63
+ behaves_the_same(@hsh, @hshlike, method_to_test, input)
64
+ end
65
+
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,422 @@
1
+ require File.expand_path('../spec_helper', File.dirname(__FILE__))
2
+ require 'gorillib/hashlike'
3
+ require 'gorillib/struct/acts_as_hash'
4
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_via_delegation')
5
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_helper')
6
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_fuzzing_helper')
7
+ require GORILLIB_ROOT_DIR('spec/support/hashlike_struct_helper')
8
+ require GORILLIB_ROOT_DIR('spec/hashlike/hashlike_behavior_spec')
9
+
10
+ describe Gorillib::Struct::ActsAsHash do
11
+
12
+ before do
13
+ @hshlike = StructUsingHashlike.new.merge(HashlikeHelper::BASE_HSH.dup)
14
+ @empty_hshlike = StructUsingHashlike.new
15
+ @hshlike_with_array_vals = StructUsingHashlike.new.merge(HashlikeHelper::BASE_HSH_WITH_ARRAY_VALS.dup)
16
+ #
17
+ @hshlike_subklass = Class.new(StructUsingHashlike)
18
+ @hshlike_subklass_inst = @hshlike_subklass.new.merge(HashlikeHelper::BASE_HSH.dup)
19
+ end
20
+
21
+
22
+ # ===========================================================================
23
+ #
24
+ # Fundamental behavior
25
+
26
+ describe '#[] and #[]= and #store' do
27
+ it_should_behave_like :hashlike_store_and_retrieve
28
+ it_should_behave_like :references_string_and_symbol_keys_equivalently, ArgumentError
29
+ it 'reject unknown keys' do
30
+ lambda{ @hshlike[:fnord] = 69 }.should raise_error NameError, /no member 'fnord' in struct/
31
+ lambda{ @hshlike[:fnord] }.should raise_error NameError, /no member 'fnord' in struct/
32
+ @hshlike.delete(:fnord).should be_nil
33
+ end
34
+ it 'accepts defined but unset keys' do
35
+ @hshlike[:new_key].should be_nil
36
+ @hshlike[:new_key] = 69
37
+ @hshlike[:new_key].should == 69
38
+ end
39
+ it 'does not allow nil, Object, and other non-stringy keys' do
40
+ lambda{ @hshlike[300] = :i_haz_num }.should raise_error(IndexError, /offset 300 too large for struct/)
41
+ lambda{ @hshlike[nil] = :i_haz_nil }.should raise_error(TypeError, "no implicit conversion from nil to integer")
42
+ obj = Object.new
43
+ lambda{ @hshlike[obj] = :i_haz_obj }.should raise_error(TypeError, "can't convert Object into Integer")
44
+ def obj.to_sym() :c ; end
45
+ lambda{ @hshlike[obj] = :i_haz_obj }.should raise_error(TypeError, "can't convert Object into Integer")
46
+ end
47
+ end
48
+
49
+ describe '#delete' do
50
+ it 'removes the key/value association and returns the value' do
51
+ @hshlike.delete(:a).should == 100
52
+ @hshlike.delete(:is_missing).should be_nil
53
+ @hshlike.delete(:false_val).should == false
54
+ @hshlike.should be_hash_eql({ :b => 200, :c => 300, :nil_val => nil })
55
+ end
56
+ describe 'with optional code block' do
57
+ it 'returns the value of executing the block (passing in the key)' do
58
+ set_in_block = nil
59
+ ret_val = @hshlike.delete(:is_missing){|k| set_in_block = "got: #{k}" ; "hello!" }
60
+ set_in_block.should == "got: is_missing"
61
+ ret_val.should == "hello!"
62
+ end
63
+ end
64
+ it 'will have a nil value but will still include? key after deleting' do
65
+ @hshlike.should include(:a)
66
+ @hshlike.delete(:a)
67
+ @hshlike.should include(:a)
68
+ @hshlike[:a].should be_nil
69
+ end
70
+ end
71
+
72
+ describe '#keys' do
73
+ it 'lists keys, even where values are nil' do
74
+ @hshlike.keys.should be_array_eql([:a, :b, :c, :nil_val, :false_val, :new_key])
75
+ @hshlike[:nil_val].should be_nil
76
+ end
77
+ it 'is the full list of members, even when nothing has been set' do
78
+ @empty_hshlike.keys.should be_array_eql([:a, :b, :c, :nil_val, :false_val, :new_key])
79
+ end
80
+ it 'is the symbolized members list' do
81
+ @empty_hshlike.keys.map(&:to_s).should == @empty_hshlike.members.map(&:to_s)
82
+ end
83
+ end
84
+
85
+ # ===========================================================================
86
+ #
87
+ # Iteration
88
+
89
+ describe '#each_pair' do
90
+ describe 'with block' do
91
+ it_should_behave_like :each_pair_on_stringlike_fixed_keys, :each_pair
92
+ end
93
+ it_should_behave_like :with_no_block_returns_enumerator, :each_pair
94
+ end
95
+
96
+ describe '#each' do
97
+ describe 'with block' do
98
+ it 'calls block once for each *val* in hsh !like array not hash!' do
99
+ seen_arg1 = []
100
+ seen_arg2 = []
101
+ @hshlike.each{|arg1,arg2| seen_arg1 << arg1 ; seen_arg2 << arg2 }
102
+ seen_arg1.should be_array_eql([100, 200, 300, nil, false, nil])
103
+ seen_arg2.should be_array_eql([nil, nil, nil, nil, nil, nil])
104
+ end
105
+ it 'with arity 1, returns keys only' do
106
+ seen_args = []
107
+ @hshlike.each{|arg| seen_args << arg }
108
+ seen_args.should be_array_eql([100, 200, 300, nil, false, nil])
109
+ end
110
+ it 'handles array keys' do
111
+ seen_args = []
112
+ @hshlike_with_array_vals.each{|arg1, arg2, arg3| seen_args << [arg1, arg2, arg3] }
113
+ seen_args.should be_array_eql([[100, 111, nil], [200, nil, nil], [1, [2, 3, [4, 5, 6]], nil], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil]])
114
+ seen_args = []
115
+ @hshlike_with_array_vals.each{|(arg1, arg2), arg3| seen_args << [arg1, arg2, arg3] }
116
+ seen_args.should be_array_eql([[100, nil, 111], [200, nil, nil], [1, nil, [2, 3, [4, 5, 6]]], [nil, nil, nil], [nil, nil, nil], [nil, nil, nil]])
117
+ end
118
+ it 'returns self' do
119
+ ret_val = @hshlike.each{|k,v| 3 }
120
+ ret_val.should equal(@hshlike)
121
+ end
122
+ end
123
+ it_should_behave_like :with_no_block_returns_enumerator, :each
124
+ end
125
+
126
+ describe '#each_key' do
127
+ describe 'with block' do
128
+ it_should_behave_like :each_key_on_stringlike_fixed_keys
129
+ end
130
+ it_should_behave_like :with_no_block_returns_enumerator, :each_key
131
+ end
132
+
133
+ describe '#each_value' do
134
+ describe 'with block' do
135
+ it_should_behave_like :each_value_on_stringlike_fixed_keys
136
+ end
137
+ it_should_behave_like :with_no_block_returns_enumerator, :each_value
138
+ end
139
+
140
+ # ===========================================================================
141
+ #
142
+ # Retrieval and Membership
143
+
144
+ describe '#values' do
145
+ it 'returns a new array populated with the values from hsh even when they were never set' do
146
+ @hshlike.values.should be_array_eql([100, 200, 300, nil, false, nil])
147
+ end
148
+ end
149
+
150
+ describe '#values_at' do
151
+ it 'takes positional, not symbol args' do
152
+ @hshlike.values_at(1, 0, 3, 5).should == [200, 100, nil, nil]
153
+ @hshlike.values_at(1, 1, 5, 3, 2, 5).should == [200, 200, nil, nil, 300, nil]
154
+ end
155
+ end
156
+
157
+ describe '#values_of' do
158
+ it_should_behave_like :hashlike_values_at_or_of, :values_of
159
+ end
160
+
161
+ describe '#length' do
162
+ it 'returns the number of key/value pairs in the hashlike' do
163
+ @hshlike.length.should == 6
164
+ @hshlike.length.should == @hshlike.members.length
165
+ @hshlike.delete(:a)
166
+ @hshlike.delete(:b)
167
+ @hshlike.length.should == 6
168
+ end
169
+ it 'is always the length of #members, regardless of contents' do
170
+ @empty_hshlike.length.should == 6
171
+ end
172
+ end
173
+
174
+ describe '#size' do
175
+ it 'returns the number of key/value pairs in the hashlike' do
176
+ @hshlike.size.should == 6
177
+ @hshlike.size.should == @hshlike.members.size
178
+ @hshlike.delete(:a)
179
+ @hshlike.delete(:b)
180
+ @hshlike.size.should == 6
181
+ end
182
+ it 'is always the length of #members, regardless of contents' do
183
+ @empty_hshlike.size.should == 6
184
+ end
185
+ end
186
+
187
+ describe '#has_key?' do
188
+ it_should_behave_like :hashlike_has_key_predefined_always_present, :has_key?
189
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :has_key?
190
+ end
191
+
192
+ describe '#include?' do
193
+ it_should_behave_like :hashlike_has_key_predefined_always_present, :include?
194
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :include?
195
+ end
196
+
197
+ describe '#key?' do
198
+ it_should_behave_like :hashlike_has_key_predefined_always_present, :key?
199
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :key?
200
+ end
201
+
202
+ describe '#member?' do
203
+ it_should_behave_like :hashlike_has_key_predefined_always_present, :member?
204
+ it_should_behave_like :hashlike_has_key_string_and_symbol_equivalent, :member?
205
+ end
206
+
207
+ describe '#has_value?' do
208
+ it_should_behave_like :hashlike_has_value?, :has_value?
209
+ end
210
+
211
+ describe '#value?' do
212
+ it_should_behave_like :hashlike_has_value?, :value?
213
+ end
214
+
215
+ describe '#fetch' do
216
+ it 'returns a value from the hashlike for the given key' do
217
+ @hshlike.fetch(:a).should == 100
218
+ @hshlike.fetch(:c).should == 300
219
+ @hshlike.fetch(:nil_val).should == nil
220
+ end
221
+ describe 'on a missing key' do
222
+ it 'with no other arguments, raises a +KeyError+ exception' do
223
+ lambda{ @hshlike.fetch(:is_missing) }.should raise_error(KeyError, 'key not found: :is_missing')
224
+ end
225
+ it 'if block given, runs the block with the given key and returns its value' do
226
+ set_in_block = nil
227
+ ret_val = @hshlike.fetch(:is_missing){|k| set_in_block = "got: #{k}" ; "hello!" }
228
+ ret_val.should == "hello!"
229
+ set_in_block.should == "got: is_missing"
230
+ end
231
+ it 'if default given, returns the default arg' do
232
+ ret_val = @hshlike.fetch(:is_missing, :returned_as_default)
233
+ ret_val.should == :returned_as_default
234
+ end
235
+ it 'if block and default are both given, issues a warning and runs the block' do
236
+ set_in_block = nil
237
+ ret_val = @hshlike.fetch(:is_missing, :spurious_default){|k| set_in_block = "got: #{k}" ; "hello!" }
238
+ ret_val.should == "hello!"
239
+ set_in_block.should == "got: is_missing"
240
+ end
241
+ end
242
+ it 'something something convert_key' unless ENV['QUIET_RSPEC']
243
+ end
244
+
245
+ describe '#key' do
246
+ it_should_behave_like :hashlike_key
247
+ end
248
+
249
+ describe '#assoc' do
250
+ it_should_behave_like :hashlike_assoc
251
+ end
252
+
253
+ describe '#rassoc' do
254
+ it_should_behave_like :hashlike_rassoc
255
+ end
256
+
257
+ describe '#empty?' do
258
+ it 'returns true if the hashlike contains only nil values, false otherwise' do
259
+ @hshlike.empty?.should == false
260
+ @empty_hshlike.empty?.should == true
261
+ @empty_hshlike[:a] = false
262
+ @empty_hshlike.empty?.should == false
263
+ end
264
+ end
265
+
266
+ # ===========================================================================
267
+ #
268
+ # Update, merge!, merge
269
+ #
270
+
271
+ describe 'update' do
272
+ it_should_behave_like :merging_method, :update
273
+ it_should_behave_like :merging_method_with_struct_keys, :update
274
+ it_should_behave_like :merging_method_inplace, :update
275
+ end
276
+
277
+ describe '#merge!' do
278
+ it_should_behave_like :merging_method, :merge!
279
+ it_should_behave_like :merging_method_with_struct_keys, :merge!
280
+ it_should_behave_like :merging_method_inplace, :merge!
281
+ end
282
+
283
+ describe '#merge' do
284
+ it_should_behave_like :merging_method, :merge
285
+ it_should_behave_like :merging_method_with_struct_keys, :merge
286
+ it_should_behave_like :merging_method_returning_new, :merge
287
+ end
288
+
289
+ # ===========================================================================
290
+ #
291
+ # Filters
292
+
293
+ shared_examples_for :hashlike_filter_fixed_keys do |method_to_test|
294
+ it 'passes every key-value pair to block' do
295
+ seen_args = []
296
+ ret_val = @hshlike.send(method_to_test){|key,val| seen_args << [key, val] ; val && (val.to_i > 150) }
297
+ #
298
+ seen_args.should be_array_eql([[:a, 100], [:b, 200], [:c, 300], [:nil_val, nil], [:false_val, false], [:new_key, nil]])
299
+ end
300
+ it 'adapts to the arity of the block' do
301
+ seen_args = []
302
+ ret_val = @hshlike.send(method_to_test){|arg| seen_args << [arg] ; @hshlike[arg] && (@hshlike[arg].to_i > 150) }
303
+ #
304
+ seen_args.should be_array_eql([[:a], [:b], [:c], [:nil_val], [:false_val], [:new_key]])
305
+ end
306
+ describe 'with no block' do
307
+ it('returns an enumerator'){ @hshlike.send(method_to_test).should enumerate_method(@hshlike, method_to_test) }
308
+ end
309
+ end
310
+
311
+ describe '#reject!' do
312
+ it_should_behave_like :hashlike_filter_fixed_keys, :reject!
313
+ it_should_behave_like :rejection_filter, :reject!
314
+ it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :reject!, false
315
+ end
316
+
317
+ describe '#select!' do
318
+ it_should_behave_like :hashlike_filter_fixed_keys, :select!
319
+ it_should_behave_like :selection_filter, :select!
320
+ it_should_behave_like :filter_modifies_self_returns_nil_if_unchanged, :select!, true
321
+ end
322
+
323
+ describe '#delete_if' do
324
+ it_should_behave_like :hashlike_filter_fixed_keys, :delete_if
325
+ it_should_behave_like :rejection_filter, :delete_if
326
+ it_should_behave_like :filter_modifies_self_returns_self, :delete_if, false
327
+ end
328
+
329
+ describe '#keep_if' do
330
+ it_should_behave_like :hashlike_filter_fixed_keys, :keep_if
331
+ it_should_behave_like :selection_filter, :keep_if
332
+ it_should_behave_like :filter_modifies_self_returns_self, :keep_if, true
333
+ end
334
+
335
+ # describe '#reject' do
336
+ # it_should_behave_like :hashlike_filter_fixed_keys, :select
337
+ # it_should_behave_like :selection_filter, :select
338
+ # it_should_behave_like :filter_does_not_modify_self_returns_same_class, :reject, false
339
+ # end
340
+ #
341
+ # describe '#select' do
342
+ # it_should_behave_like :hashlike_filter_fixed_keys, :select
343
+ # it_should_behave_like :selection_filter, :select
344
+ # it_should_behave_like :filter_does_not_modify_self_returns_same_class, :select, true
345
+ # end
346
+
347
+ describe '#clear' do
348
+ it_should_behave_like :hashlike_clear
349
+ end
350
+
351
+ # ===========================================================================
352
+ #
353
+ # Conversion
354
+
355
+ describe '#to_hash' do
356
+ it 'returns a new Hash with each key set to its associated value' do
357
+ ret_val = @hshlike.to_hash
358
+ ret_val.should be_an_instance_of(Hash)
359
+ ret_val.should == {:a=>100, :b=>200, :c=>300, :nil_val=>nil, :false_val=>false, :new_key=>nil}
360
+ end
361
+ end
362
+
363
+ if (RUBY_VERSION >= '1.9')
364
+ describe '#invert' do
365
+ it 'returns a new Hash using the values as keys, and the keys as values' do
366
+ ret_val = @hshlike.invert
367
+ ret_val.should == { 100 => :a, 200 => :b, 300 => :c, nil => :new_key, false => :false_val }
368
+ end
369
+ it 'with duplicate values, the result will contain only one of them as a key' do
370
+ @hshlike[:a] = 999
371
+ @hshlike[:new_key] = 999
372
+ @hshlike.invert.should == { 999 => :new_key, 200 => :b, 300 => :c, nil => :nil_val, false => :false_val }
373
+ end
374
+ it 'returns a Hash, not a self.class' do
375
+ ret_val = @hshlike.invert
376
+ ret_val.should be_an_instance_of(Hash)
377
+ end
378
+ end
379
+
380
+ describe '#flatten' do
381
+ it 'with no arg returns a one-dimensional flattening' do
382
+ ret_val = @hshlike_with_array_vals.flatten
383
+ ret_val.should == [ :a, [100, 111], :b, 200, :c, [1, [2, 3, [4, 5, 6]]], :nil_val, nil, :false_val, nil, :new_key, nil ]
384
+ end
385
+ it 'with no arg is same as level = 1' do
386
+ @hshlike_with_array_vals.flatten(1).should == @hshlike_with_array_vals.flatten
387
+ end
388
+ it 'with level == nil, returns a complete flattening' do
389
+ ret_val = @hshlike_with_array_vals.flatten(nil)
390
+ ret_val.should == [ :a, 100, 111, :b, 200, :c, 1, 2, 3, 4, 5, 6, :nil_val, nil, :false_val, nil, :new_key, nil ]
391
+ end
392
+ it 'with an arg, flattens to that level (0)' do
393
+ ret_val = @hshlike_with_array_vals.flatten(0)
394
+ ret_val.should == [ [:a, [100, 111]], [:b, 200], [:c, [1, [2, 3, [4, 5, 6]]]], [:nil_val, nil], [:false_val, nil], [:new_key, nil]]
395
+ end
396
+ it 'with an arg, flattens to that level (3)' do
397
+ ret_val = @hshlike_with_array_vals.flatten(3)
398
+ ret_val.should == [ :a, 100, 111, :b, 200, :c, 1, 2, 3, [4, 5, 6], :nil_val, nil, :false_val, nil, :new_key, nil ]
399
+ end
400
+ it 'with an arg, flattens to that level (4)' do
401
+ ret_val = @hshlike_with_array_vals.flatten(4)
402
+ ret_val.should == [ :a, 100, 111, :b, 200, :c, 1, 2, 3, 4, 5, 6, :nil_val, nil, :false_val, nil, :new_key, nil ]
403
+ ret_val.should == @hshlike_with_array_vals.flatten(999)
404
+ end
405
+ end
406
+ end
407
+
408
+ # ===========================================================================
409
+ #
410
+ # Sanity check
411
+
412
+ it 'built test objects correctly' do
413
+ @hshlike_subklass .should < @hshlike.class
414
+ @hshlike_subklass .should_not == @hshlike.class
415
+ @hshlike_subklass_inst .should be_a(StructUsingHashlike)
416
+ @hshlike_subklass_inst .should be_a(@hshlike_subklass)
417
+ @hshlike_subklass_inst .should_not be_an_instance_of(StructUsingHashlike)
418
+ @hshlike .should_not be_a(@hshlike_subklass)
419
+ @hshlike .should be_an_instance_of(StructUsingHashlike)
420
+ end
421
+
422
+ end