oklahoma_mixer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +10 -0
- data/TODO.rdoc +3 -3
- data/lib/oklahoma_mixer.rb +14 -5
- data/lib/oklahoma_mixer/b_tree_database.rb +185 -0
- data/lib/oklahoma_mixer/b_tree_database/c.rb +45 -0
- data/lib/oklahoma_mixer/cursor.rb +43 -0
- data/lib/oklahoma_mixer/cursor/c.rb +45 -0
- data/lib/oklahoma_mixer/fixed_length_database.rb +95 -0
- data/lib/oklahoma_mixer/fixed_length_database/c.rb +62 -0
- data/lib/oklahoma_mixer/hash_database.rb +84 -54
- data/lib/oklahoma_mixer/hash_database/c.rb +3 -96
- data/lib/oklahoma_mixer/utilities.rb +110 -5
- data/test/b_tree_binary_data_test.rb +45 -0
- data/test/b_tree_tuning_test.rb +132 -0
- data/test/binary_data_test.rb +3 -13
- data/test/cursor_based_iteration_test.rb +151 -0
- data/test/duplicate_storage_test.rb +107 -0
- data/test/fixed_length_tuning_test.rb +77 -0
- data/test/getting_and_setting_by_id_test.rb +288 -0
- data/test/getting_and_setting_keys_test.rb +37 -3
- data/test/iteration_test.rb +2 -76
- data/test/key_range_test.rb +161 -0
- data/test/order_test.rb +122 -0
- data/test/shared_binary_data.rb +14 -0
- data/test/shared_iteration.rb +99 -0
- data/test/shared_tuning.rb +91 -0
- data/test/test_helper.rb +10 -11
- data/test/top_level_interface_test.rb +12 -0
- data/test/tuning_test.rb +11 -87
- metadata +27 -2
@@ -0,0 +1,77 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestFixedLengthTuning < Test::Unit::TestCase
|
4
|
+
def teardown
|
5
|
+
remove_db_files
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_a_mutex_can_be_activated_as_the_database_is_created
|
9
|
+
args = capture_args(OKMixer::FixedLengthDatabase::C, :setmutex) do
|
10
|
+
fdb(:mutex => true) do
|
11
|
+
# just open and close
|
12
|
+
end
|
13
|
+
end
|
14
|
+
assert_instance_of(FFI::Pointer, args[0])
|
15
|
+
assert_equal([ ], args[1..-1])
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_width_controls_value_length
|
19
|
+
fdb(:width => 4) do |db|
|
20
|
+
db.update(1 => "one", 2 => "two", 3 => "three", 4 => "four")
|
21
|
+
assert_equal([[1, "one"], [2, "two"], [3, "thre"], [4, "four"]], db.to_a)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_width_can_be_changed_later_with_optimize
|
26
|
+
fdb do |db| # default width of 255
|
27
|
+
db.update(1 => "one", 2 => "two", 3 => "three", 4 => "four")
|
28
|
+
assert_equal([[1, "one"], [2, "two"], [3, "three"], [4, "four"]], db.to_a)
|
29
|
+
assert(db.optimize(:width => 4), "Width was not changed")
|
30
|
+
assert_equal([[1, "one"], [2, "two"], [3, "thre"], [4, "four"]], db.to_a)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_limsiz_controls_the_maximum_database_size
|
35
|
+
fdb(:width => 1024, :limsiz => 3 * 1024) do |db|
|
36
|
+
data = "X" * 1024
|
37
|
+
assert_nothing_raised(OKMixer::Error::CabinetError) do
|
38
|
+
3.times do |i|
|
39
|
+
db[i + 1] = data
|
40
|
+
end
|
41
|
+
end
|
42
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
43
|
+
db[4] = "X"
|
44
|
+
end
|
45
|
+
assert_equal([[1, data], [2, data], [3, data]], db.to_a)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_limsiz_can_be_increases_later_with_optimize
|
50
|
+
fdb(:width => 1024, :limsiz => 3 * 1024) do |db|
|
51
|
+
data = "X" * 1024
|
52
|
+
3.times do |i|
|
53
|
+
db[i + 1] = data
|
54
|
+
end
|
55
|
+
assert(db.optimize(:limsiz => 4 * 1024), "Size limit was not increased")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_defrag_is_a_no_op
|
60
|
+
fdb(:width => 1024) do |db|
|
61
|
+
# load some data
|
62
|
+
data = "X" * 1024
|
63
|
+
10.times do |i|
|
64
|
+
db[i + 1] = data
|
65
|
+
end
|
66
|
+
old_size = File.size(db.path)
|
67
|
+
# delete some data
|
68
|
+
[3, 5, 7].each do |i|
|
69
|
+
db.delete(i)
|
70
|
+
end
|
71
|
+
assert_equal(old_size, File.size(db.path))
|
72
|
+
# no-op
|
73
|
+
db.defrag
|
74
|
+
assert_equal(old_size, File.size(db.path))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,288 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestGettingAndSettingByID < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@db = fdb
|
6
|
+
end
|
7
|
+
|
8
|
+
def teardown
|
9
|
+
@db.close
|
10
|
+
remove_db_files
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_a_key_value_pair_can_be_stored_and_fetched_from_the_database
|
14
|
+
assert_equal("value", @db.store(42, "value"))
|
15
|
+
assert_equal("value", @db.fetch(42)) # later
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_keys_are_converted_to_integers
|
19
|
+
assert_equal("value", @db.store(42, "value"))
|
20
|
+
assert_equal("value", @db.fetch("42")) # effectively the same key
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_the_special_ids_min_and_max_are_supported_after_ids_are_set
|
24
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
25
|
+
@db[:min]
|
26
|
+
end
|
27
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
28
|
+
@db[:max]
|
29
|
+
end
|
30
|
+
@db.update(10 => :min, 20 => :middle, 30 => :max)
|
31
|
+
assert_equal("min", @db[:min])
|
32
|
+
assert_equal("max", @db[:max])
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_the_special_id_next_can_be_used_to_set_increasing_ids
|
36
|
+
3.times do |n|
|
37
|
+
assert_equal(n, @db[:next] = n)
|
38
|
+
end
|
39
|
+
assert_equal([[1, "0"], [2, "1"], [3, "2"]], @db.to_a)
|
40
|
+
@db[7] = 6
|
41
|
+
assert_equal(7, @db[:next] = 7)
|
42
|
+
assert_equal([[1, "0"], [2, "1"], [3, "2"], [7, "6"], [8, "7"]], @db.to_a)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_the_special_id_prev_can_be_used_to_add_below_min
|
46
|
+
# no min
|
47
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
48
|
+
@db[:prev] = 100
|
49
|
+
end
|
50
|
+
|
51
|
+
@db[10] = 10
|
52
|
+
assert_equal(9, @db[:prev] = 9)
|
53
|
+
assert_equal([[9, "9"], [10, "10"]], @db.to_a)
|
54
|
+
|
55
|
+
# can't go below 1
|
56
|
+
@db[1] = 1
|
57
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
58
|
+
@db[:prev] = 100
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_fetching_a_missing_value_fails_with_an_index_error
|
63
|
+
assert_raise(IndexError) do
|
64
|
+
@db.fetch(42)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_fetch_can_return_a_default_for_a_missing_value
|
69
|
+
assert_equal(:value, @db.fetch(42, :value))
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_fetch_can_run_a_block_returning_its_result_for_a_missing_value
|
73
|
+
assert_equal(42, @db.fetch(42) { |key| key })
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_fetching_with_a_block_overrides_a_default_and_triggers_a_warning
|
77
|
+
warning = capture_stderr do
|
78
|
+
assert_equal(:returned, @db.fetch(42, :ignored) { :returned })
|
79
|
+
end
|
80
|
+
assert(!warning.empty?, "A warning was not issued for a default and block")
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_storing_with_keep_mode_adds_a_value_only_if_it_didnt_already_exist
|
84
|
+
assert(@db.store(42, :new, :keep), "Failed to store a new key")
|
85
|
+
assert_equal("new", @db.fetch(42))
|
86
|
+
assert(!@db.store(42, :replace, :keep), "Replaced an existing key")
|
87
|
+
assert_equal("new", @db.fetch(42))
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_storing_with_cat_mode_concatenates_content_onto_an_existing_value
|
91
|
+
assert_equal("One", @db.store(42, "One", :cat))
|
92
|
+
assert_equal("One", @db.fetch(42))
|
93
|
+
assert_equal(", Two", @db.store(42, ", Two", :cat))
|
94
|
+
assert_equal("One, Two", @db.fetch(42))
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_storing_with_add_mode_adds_to_an_existing_value
|
98
|
+
assert_equal(0, @db.store(42, 0, :add))
|
99
|
+
assert_equal(1, @db.store(42, 1, :add))
|
100
|
+
assert_equal(2, @db.store(42, 1, :add))
|
101
|
+
assert_equal(1, @db.store(42, -1, :add))
|
102
|
+
|
103
|
+
assert_in_delta(1.5, @db.store(100, 1.5, :add), 2 ** -20)
|
104
|
+
assert_in_delta(3.5, @db.store(100, 2.0, :add), 2 ** -20)
|
105
|
+
assert_in_delta(2.5, @db.store(100, -1.0, :add), 2 ** -20)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_adding_to_a_non_added_value_fails_with_an_error
|
109
|
+
@db[42] = 0
|
110
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
111
|
+
@db.store(42, 1, :add)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_switching_add_types_fails_with_an_error
|
116
|
+
@db.store(42, 1, :add)
|
117
|
+
@db.store(100, 1.0, :add)
|
118
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
119
|
+
@db.store(42, 2.0, :add)
|
120
|
+
end
|
121
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
122
|
+
@db.store(100, 2, :add)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_storing_with_a_block_allows_duplicate_resolution
|
127
|
+
@db[42] = :old
|
128
|
+
assert_equal( :new, @db.store(42, :new) { |key, old, new|
|
129
|
+
"#{key}=#{old}&#{new}" } )
|
130
|
+
assert_equal("42=old&new", @db[42])
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_storing_with_a_block_overrides_a_mode_and_triggers_a_warning
|
134
|
+
warning = capture_stderr do
|
135
|
+
assert_equal(:new, @db.store(42, :new, :cat) { |key, old, new| })
|
136
|
+
end
|
137
|
+
assert(!warning.empty?, "A warning was not issued for a mode and block")
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_storing_with_a_mode_not_supported_by_the_database_triggers_a_warning
|
141
|
+
warning = capture_stderr do
|
142
|
+
assert_equal(:value, @db.store(42, :value, :async)) # normal store
|
143
|
+
end
|
144
|
+
assert(!warning.empty?, "A warning was not issued for an unsupported mode")
|
145
|
+
assert_equal("value", @db[42])
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_store_and_fetch_can_also_be_used_through_the_indexing_brackets
|
149
|
+
assert_equal(:value, @db[42] = :value)
|
150
|
+
assert_equal("value", @db[42])
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_indexing_returns_nil_instead_of_failing_with_index_error
|
154
|
+
assert_nil(@db[42])
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_a_default_can_be_set_for_indexing_to_return
|
158
|
+
@db.default = :default
|
159
|
+
assert_equal(:default, @db[42])
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_the_indexing_default_will_be_run_if_it_is_a_proc
|
163
|
+
@db.default = lambda { |key| "is #{key}" }
|
164
|
+
assert_equal("is 42", @db[42])
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_the_indexing_default_for_a_given_key_can_be_retrieved
|
168
|
+
@db.default = lambda { |key| "is #{key}" }
|
169
|
+
assert_equal("is ", @db.default)
|
170
|
+
assert_equal("is 42", @db.default(42))
|
171
|
+
end
|
172
|
+
|
173
|
+
def test_the_indexing_default_can_be_changed
|
174
|
+
assert_nil(@db[42])
|
175
|
+
assert_equal(:default, @db.default = :default)
|
176
|
+
assert_equal(:default, @db[:missing])
|
177
|
+
proc = lambda { |key| fail RuntimeError, "%p not found" % [key]}
|
178
|
+
assert_equal(proc, @db.default = proc)
|
179
|
+
error = assert_raise(RuntimeError) { @db[42] }
|
180
|
+
assert_equal("42 not found", error.message)
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_include_and_aliases_can_be_used_to_check_for_the_existance_of_a_key
|
184
|
+
@db[42] = true
|
185
|
+
%w[include? has_key? key? member?].each do |query|
|
186
|
+
assert(@db.send(query, 42), "Failed to detect an existing key")
|
187
|
+
assert(!@db.send(query, 100), "Failed to detect an missing key")
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_update_sets_multiple_values_at_once_overwriting_old_values
|
192
|
+
@db[42] = "old_42"
|
193
|
+
assert_equal(@db, @db.update(1 => "new_1", 42 => "new_42", 3 => "new_3"))
|
194
|
+
assert_equal(%w[new_1 new_42 new_3], @db.values_at(1, 42, 3))
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_update_can_be_passed_a_block_for_handling_duplicates
|
198
|
+
@db[42] = "old"
|
199
|
+
assert_equal( @db, @db.update( 1 => "new",
|
200
|
+
42 => "new",
|
201
|
+
3 => "new") { |key, old, new|
|
202
|
+
"#{key}=#{old}&#{new}" } )
|
203
|
+
assert_equal(%w[new 42=old&new new], @db.values_at(1, 42, 3))
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_values_at_can_be_used_to_retrieve_multiple_values_at_once
|
207
|
+
@db[1] = 100
|
208
|
+
@db[3] = 300
|
209
|
+
assert_equal([ ], @db.values_at)
|
210
|
+
assert_equal(["100", nil, "300"], @db.values_at(1, 42, 3))
|
211
|
+
end
|
212
|
+
|
213
|
+
def test_values_at_supports_defaults
|
214
|
+
@db.default = 42
|
215
|
+
@db[1] = 100
|
216
|
+
@db[3] = 300
|
217
|
+
assert_equal(["100", 42, "300"], @db.values_at(1, 42, 3))
|
218
|
+
end
|
219
|
+
|
220
|
+
def test_keys_returns_all_keys_in_the_database
|
221
|
+
@db.update(1 => 100, 2 => 200, 3 => 300)
|
222
|
+
assert_equal([1, 2, 3], @db.keys)
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_keys_does_not_support_prefix_for_fixed_length_databases
|
226
|
+
assert_raise(ArgumentError) do
|
227
|
+
@db.keys(:prefix => "1")
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_keys_can_take_a_limit_of_keys_to_return
|
232
|
+
@db.update(1 => 100, 42 => 4200, 3 => 300)
|
233
|
+
assert_equal([1, 3], @db.keys(:limit => 2))
|
234
|
+
end
|
235
|
+
|
236
|
+
def test_values_returns_all_values_in_the_database
|
237
|
+
@db.update(1 => 100, 2 => 200, 3 => 300)
|
238
|
+
assert_equal(%w[100 200 300], @db.values)
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_delete_removes_a_key_from_the_database
|
242
|
+
@db[42] = :value
|
243
|
+
assert_equal("value", @db.delete(42))
|
244
|
+
assert_nil(@db[42])
|
245
|
+
end
|
246
|
+
|
247
|
+
def test_delete_returns_nil_for_a_missing_key
|
248
|
+
assert_nil(@db.delete(42))
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_delete_can_be_passed_a_block_to_handle_missing_keys
|
252
|
+
assert_equal(:value, @db.delete(42) { :value })
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_clear_removes_all_keys_from_the_database
|
256
|
+
@db.update(1 => 100, 2 => 200, 3 => 300)
|
257
|
+
assert_equal(@db, @db.clear)
|
258
|
+
assert_equal([nil, nil, nil], @db.values_at(1, 2, 3))
|
259
|
+
end
|
260
|
+
|
261
|
+
def test_size_and_length_return_the_count_of_key_value_pairs_in_the_database
|
262
|
+
assert_equal(0, @db.size)
|
263
|
+
assert_equal(0, @db.length)
|
264
|
+
@db.update(1 => 100, 2 => 200, 3 => 300)
|
265
|
+
assert_equal(3, @db.size)
|
266
|
+
assert_equal(3, @db.length)
|
267
|
+
end
|
268
|
+
|
269
|
+
def test_each_key_iterates_over_ids
|
270
|
+
@db.update(1 => 100, 2 => 200, 3 => 300)
|
271
|
+
keys = [1, 2, 3]
|
272
|
+
@db.each_key do |key|
|
273
|
+
assert_equal(keys.shift, key)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_each_and_each_pair_iterate_over_ids_and_values
|
278
|
+
@db.update(1 => 100, 2 => 200, 3 => 300)
|
279
|
+
%w[each each_pair].each do |iterator|
|
280
|
+
keys = [1, 2, 3]
|
281
|
+
values = %w[100 200 300]
|
282
|
+
@db.send(iterator) do |key, value|
|
283
|
+
assert_equal(keys.shift, key)
|
284
|
+
assert_equal(values.shift, value)
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
@@ -68,12 +68,30 @@ class TestGettingAndSettingKeys < Test::Unit::TestCase
|
|
68
68
|
assert_equal(1, @db.store(:i, 1, :add))
|
69
69
|
assert_equal(2, @db.store(:i, 1, :add))
|
70
70
|
assert_equal(1, @db.store(:i, -1, :add))
|
71
|
-
|
71
|
+
|
72
72
|
assert_in_delta(1.5, @db.store(:f, 1.5, :add), 2 ** -20)
|
73
73
|
assert_in_delta(3.5, @db.store(:f, 2.0, :add), 2 ** -20)
|
74
74
|
assert_in_delta(2.5, @db.store(:f, -1.0, :add), 2 ** -20)
|
75
75
|
end
|
76
76
|
|
77
|
+
def test_adding_to_a_non_added_value_fails_with_an_error
|
78
|
+
@db[:i] = 42
|
79
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
80
|
+
@db.store(:i, 1, :add)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_switching_add_types_fails_with_an_error
|
85
|
+
@db.store(:i, 1, :add)
|
86
|
+
@db.store(:f, 1.0, :add)
|
87
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
88
|
+
@db.store(:i, 2.0, :add)
|
89
|
+
end
|
90
|
+
assert_raise(OKMixer::Error::CabinetError) do
|
91
|
+
@db.store(:f, 2, :add)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
77
95
|
def test_storing_with_a_block_allows_duplicate_resolution
|
78
96
|
@db[:key] = :old
|
79
97
|
assert_equal( :new, @db.store(:key, :new) { |key, old, new|
|
@@ -88,6 +106,22 @@ class TestGettingAndSettingKeys < Test::Unit::TestCase
|
|
88
106
|
assert(!warning.empty?, "A warning was not issued for a mode and block")
|
89
107
|
end
|
90
108
|
|
109
|
+
def test_storing_with_a_mode_not_supported_by_the_database_triggers_a_warning
|
110
|
+
warning = capture_stderr do
|
111
|
+
assert_equal(:one, @db.store(:dups, :one, :dup)) # normal store
|
112
|
+
end
|
113
|
+
assert(!warning.empty?, "A warning was not issued for an unsupported mode")
|
114
|
+
assert_equal("one", @db[:dups])
|
115
|
+
|
116
|
+
bdb do |db|
|
117
|
+
warning = capture_stderr do
|
118
|
+
assert_equal(:value, db.store(:key, :value, :async)) # normal store
|
119
|
+
end
|
120
|
+
assert(!warning.empty?, "A warning was not issued for an unsupported mode")
|
121
|
+
assert_equal("value", db[:key])
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
91
125
|
def test_store_and_fetch_can_also_be_used_through_the_indexing_brackets
|
92
126
|
assert_equal(42, @db[:num] = 42)
|
93
127
|
assert_equal("42", @db[:num])
|
@@ -155,8 +189,8 @@ class TestGettingAndSettingKeys < Test::Unit::TestCase
|
|
155
189
|
|
156
190
|
def test_values_at_supports_defaults
|
157
191
|
@db.default = 42
|
158
|
-
@db[:a]
|
159
|
-
@db[:c]
|
192
|
+
@db[:a] = 1
|
193
|
+
@db[:c] = 2
|
160
194
|
assert_equal(["1", 42, "2"], @db.values_at(:a, :b, :c))
|
161
195
|
end
|
162
196
|
|
data/test/iteration_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "test_helper"
|
2
|
+
require "shared_iteration"
|
2
3
|
|
3
4
|
class TestIteration < Test::Unit::TestCase
|
4
5
|
def setup
|
@@ -15,80 +16,5 @@ class TestIteration < Test::Unit::TestCase
|
|
15
16
|
remove_db_files
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
-
@db.each_key do |key|
|
20
|
-
@keys.delete(key)
|
21
|
-
end
|
22
|
-
assert(@keys.empty?, "All keys were not iterated over")
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_each_iterates_over_all_key_value_pairs_in_arrays
|
26
|
-
@db.each do |key_value_array|
|
27
|
-
assert_instance_of(Array, key_value_array)
|
28
|
-
assert_equal(2, key_value_array.size)
|
29
|
-
key, value = key_value_array
|
30
|
-
assert_equal(key * 2, value)
|
31
|
-
@keys.delete(key)
|
32
|
-
@values.delete(value)
|
33
|
-
end
|
34
|
-
assert( @keys.empty? && @values.empty?,
|
35
|
-
"All key/value pairs were not iterated over" )
|
36
|
-
end
|
37
|
-
|
38
|
-
def test_the_arrays_passed_to_each_can_be_split
|
39
|
-
@db.each do |key, value|
|
40
|
-
@keys.delete(key)
|
41
|
-
@values.delete(value)
|
42
|
-
end
|
43
|
-
assert( @keys.empty? && @values.empty?,
|
44
|
-
"All key/value pairs were not iterated over" )
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_each_pair_is_an_alias_for_each
|
48
|
-
each_arrays = [ ]
|
49
|
-
@db.each do |array|
|
50
|
-
each_arrays << array
|
51
|
-
end
|
52
|
-
@db.each_pair do |array|
|
53
|
-
each_arrays.delete(array)
|
54
|
-
end
|
55
|
-
each_keys_and_values = [ ]
|
56
|
-
@db.each do |key, value|
|
57
|
-
each_keys_and_values << [key, value]
|
58
|
-
end
|
59
|
-
@db.each_pair do |key, value|
|
60
|
-
each_keys_and_values.delete([key, value])
|
61
|
-
end
|
62
|
-
assert( each_arrays.empty? && each_keys_and_values.empty?,
|
63
|
-
"The iterations did not match" )
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_each_value_iterates_over_all_values_in_the_database
|
67
|
-
@db.each_value do |value|
|
68
|
-
@values.delete(value)
|
69
|
-
end
|
70
|
-
assert(@values.empty?, "All values were not iterated over")
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_the_standard_iterators_are_supported
|
74
|
-
assert_kind_of(Enumerable, @db)
|
75
|
-
|
76
|
-
# examples
|
77
|
-
assert_equal(%w[b bb], @db.find { |_, value| value == "bb" })
|
78
|
-
assert_nil(@db.find { |_, value| value == "dd" })
|
79
|
-
assert_equal(%w[aaa bbb ccc], @db.map { |key, value| key + value }.sort)
|
80
|
-
assert( @db.any? { |_, value| value.include? "c" },
|
81
|
-
"A value was not found during iteration" )
|
82
|
-
end
|
83
|
-
|
84
|
-
def test_delete_if_removes_all_keys_for_which_the_block_returns_true
|
85
|
-
@db.delete_if { |key, _| key != "a" }
|
86
|
-
assert_equal([%w[a aa]], @db.to_a)
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_iterators_return_self_to_match_hash_interface
|
90
|
-
%w[each_key each each_pair each_value delete_if].each do |iterator|
|
91
|
-
assert_equal(@db, @db.send(iterator) { })
|
92
|
-
end
|
93
|
-
end
|
19
|
+
include SharedIteration
|
94
20
|
end
|