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.
@@ -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] = 1
159
- @db[:c] = 2
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
 
@@ -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
- def test_each_key_iterates_over_all_keys_in_the_database
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