oklahoma_mixer 0.1.0 → 0.2.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.
- 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
|