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,161 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestKeyRange < Test::Unit::TestCase
|
4
|
+
def teardown
|
5
|
+
remove_db_files
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_b_tree_supports_non_range_key_requests
|
9
|
+
abc_db do |db|
|
10
|
+
assert_equal(%w[a b], db.keys(:limit => 2))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_keys_can_return_a_range_of_keys_for_a_b_tree_database
|
15
|
+
abc_db do |db|
|
16
|
+
assert_equal(%w[b c], db.keys(:range => "b".."c"))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_range_overrides_prefix_and_triggers_a_warning
|
21
|
+
abc_db do |db|
|
22
|
+
warning = capture_stderr do
|
23
|
+
# returns range
|
24
|
+
assert_equal(%w[b c], db.keys(:range => "b".."c", :prefix => "ignored"))
|
25
|
+
end
|
26
|
+
assert(!warning.empty?, "A warning was not issued for a range and prefix")
|
27
|
+
end
|
28
|
+
|
29
|
+
num_db do |db|
|
30
|
+
warning = capture_stderr do
|
31
|
+
# returns range
|
32
|
+
assert_equal([2, 3], db.keys(:range => 2..3, :prefix => "ignored"))
|
33
|
+
end
|
34
|
+
assert(!warning.empty?, "A warning was not issued for a range and prefix")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_b_tree_key_ranges_must_be_passed_a_range_object
|
39
|
+
abc_db do |db|
|
40
|
+
assert_nothing_raised(ArgumentError) do
|
41
|
+
db.keys(:range => "b".."c")
|
42
|
+
end
|
43
|
+
assert_raise(ArgumentError) do
|
44
|
+
db.keys(:range => "not a Range")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_boundaries_are_converted_to_strings_for_a_b_tree_database
|
50
|
+
abc_db do |db|
|
51
|
+
assert_equal(%w[b c], db.keys(:range => %w[b]..%w[c]))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_key_ranges_can_exclude_the_last_member_in_a_b_tree_database
|
56
|
+
abc_db do |db|
|
57
|
+
assert_equal(%w[b], db.keys(:range => "b"..."c"))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_key_ranges_can_exclude_the_first_member_in_a_b_tree_database
|
62
|
+
abc_db do |db|
|
63
|
+
assert_equal(%w[c], db.keys(:range => "b".."c", :exclude_start => true))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_key_ranges_can_use_values_between_keys_in_a_b_tree_database
|
68
|
+
abc_db do |db|
|
69
|
+
assert_equal(%w[b c], db.keys(:range => "ab".."f"))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_a_limit_can_be_set_for_key_ranges_in_a_b_tree_database
|
74
|
+
abc_db do |db|
|
75
|
+
assert_equal(%w[b], db.keys(:range => "b".."c", :limit => 1))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_range_queries_work_with_custom_ordering
|
80
|
+
bdb(:cmpfunc => lambda { |a, b| a.to_i <=> b.to_i }) do |db|
|
81
|
+
db.update(1 => :a, 11 => :b, 2 => :c)
|
82
|
+
assert_equal(%w[2 11], db.keys(:range => 2..100))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_fixed_length_supports_non_range_key_requests
|
87
|
+
num_db do |db|
|
88
|
+
assert_equal([1, 2], db.keys(:limit => 2))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_keys_can_return_a_range_of_keys_for_a_fixed_length_database
|
93
|
+
num_db do |db|
|
94
|
+
assert_equal([2, 3], db.keys(:range => 2..3))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_fixed_length_key_ranges_must_be_passed_a_range_or_array
|
99
|
+
num_db do |db|
|
100
|
+
assert_nothing_raised(ArgumentError) do
|
101
|
+
db.keys(:range => "min".."max")
|
102
|
+
end
|
103
|
+
assert_nothing_raised(ArgumentError) do
|
104
|
+
db.keys(:range => [:min, 100])
|
105
|
+
end
|
106
|
+
assert_raise(ArgumentError) do
|
107
|
+
db.keys(:range => "not a Range")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_boundaries_are_converted_to_integers_for_a_fixed_length_database
|
113
|
+
num_db do |db|
|
114
|
+
assert_equal([2, 3], db.keys(:range => "2".."3"))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_key_ranges_can_exclude_the_last_member_in_a_fixed_length_database
|
119
|
+
num_db do |db|
|
120
|
+
assert_equal([2], db.keys(:range => 2...3))
|
121
|
+
assert_equal([2], db.keys(:range => [2, 3], :exclude_end => true))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def test_key_ranges_can_exclude_the_first_member_in_a_fixed_length_database
|
126
|
+
num_db do |db|
|
127
|
+
assert_equal([3], db.keys(:range => 2..3, :exclude_start => true))
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_key_ranges_can_use_values_between_keys_in_a_fixed_length_database
|
132
|
+
num_db do |db|
|
133
|
+
db.update(5 => 500, 6 => 600)
|
134
|
+
assert_equal([5, 6], db.keys(:range => 4..7))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_a_limit_can_be_set_for_key_ranges_in_a_fixed_length_database
|
139
|
+
num_db do |db|
|
140
|
+
assert_equal([2], db.keys(:range => 2..3, :limit => 1))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
#######
|
145
|
+
private
|
146
|
+
#######
|
147
|
+
|
148
|
+
def abc_db
|
149
|
+
bdb do |db|
|
150
|
+
db.update(:a => 1, :b => 2, :c => 3)
|
151
|
+
yield db
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def num_db
|
156
|
+
fdb do |db|
|
157
|
+
db.update(1 => 100, 2 => 200, 3 => 300)
|
158
|
+
yield db
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/test/order_test.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestOrder < Test::Unit::TestCase
|
4
|
+
REVERSE_ORDER_CMPFUNC = lambda { |a, b| a == "" ? a <=> b : b <=> a }
|
5
|
+
|
6
|
+
def teardown
|
7
|
+
remove_db_files
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_b_tree_databases_default_to_lexical_ordering
|
11
|
+
bdb do |db|
|
12
|
+
db.update(:c => 3, :a => 1, :b => 2)
|
13
|
+
assert_equal(%w[a b c], db.keys)
|
14
|
+
assert_equal([%w[a 1], %w[b 2], %w[c 3]], db.to_a)
|
15
|
+
end
|
16
|
+
|
17
|
+
remove_db_files
|
18
|
+
bdb do |db|
|
19
|
+
db.update(1 => :a, 11 => :b, 2 => :c)
|
20
|
+
assert_equal(%w[1 11 2], db.keys)
|
21
|
+
assert_equal([%w[1 a], %w[11 b], %w[2 c]], db.to_a)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_b_tree_database_ordering_can_be_changed_with_a_comparison_function
|
26
|
+
bdb(:cmpfunc => REVERSE_ORDER_CMPFUNC) do |db|
|
27
|
+
db.update(:c => 3, :a => 1, :b => 2)
|
28
|
+
assert_equal(%w[c b a], db.keys)
|
29
|
+
assert_equal([%w[c 3], %w[b 2], %w[a 1]], db.to_a)
|
30
|
+
end
|
31
|
+
|
32
|
+
remove_db_files
|
33
|
+
cmpfunc = lambda { |a, b| a.to_i <=> b.to_i } # numerical order
|
34
|
+
bdb(:cmpfunc => cmpfunc) do |db|
|
35
|
+
db.update(1 => :a, 11 => :b, 2 => :c)
|
36
|
+
assert_equal(%w[1 2 11], db.keys)
|
37
|
+
assert_equal([%w[1 a], %w[2 c], %w[11 b]], db.to_a)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_each_key_iterates_through_keys_in_order_for_b_trees
|
42
|
+
assert_forward_iteration(%w[a b c], :each_key)
|
43
|
+
assert_reverse_iteration(%w[c b a], :each_key)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_each_iterates_through_key_value_pairs_in_order_for_b_trees
|
47
|
+
assert_forward_iteration([%w[a 1], %w[b 2], %w[c 3]], :each)
|
48
|
+
assert_reverse_iteration([%w[c 3], %w[b 2], %w[a 1]], :each)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_reverse_each_iterates_through_key_value_pairs_in_revserse_order
|
52
|
+
assert_forward_iteration([%w[c 3], %w[b 2], %w[a 1]], :reverse_each)
|
53
|
+
assert_reverse_iteration([%w[a 1], %w[b 2], %w[c 3]], :reverse_each)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_each_value_iterates_through_values_in_order_for_b_trees
|
57
|
+
assert_forward_iteration(%w[1 2 3], :each_value)
|
58
|
+
assert_reverse_iteration(%w[3 2 1], :each_value)
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_delete_if_iterates_through_key_value_pairs_in_order_for_b_trees
|
62
|
+
assert_forward_iteration([%w[a 1], %w[b 2], %w[c 3]], :delete_if)
|
63
|
+
assert_reverse_iteration([%w[c 3], %w[b 2], %w[a 1]], :delete_if)
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_fixed_length_databases_have_numerical_ordering_by_keys
|
67
|
+
fdb do |db|
|
68
|
+
db.update(3 => 300, 1 => 100, 2 => 200)
|
69
|
+
assert_equal([1, 2, 3], db.keys)
|
70
|
+
assert_equal([[1, "100"], [2, "200"], [3, "300"]], db.to_a)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_each_key_iterates_through_keys_in_order_for_fixed_lengths
|
75
|
+
assert_forward_iteration([1, 2, 3], :each_key, :fdb)
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_each_iterates_through_key_value_pairs_in_order_for_fixed_lengths
|
79
|
+
assert_forward_iteration([[1, "100"], [2, "200"], [3, "300"]], :each, :fdb)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_each_value_iterates_through_values_in_order_for_fixed_lengths
|
83
|
+
assert_forward_iteration(%w[100 200 300], :each_value, :fdb)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_delete_if_iterates_through_key_value_pairs_in_order_for_fixed_lengths
|
87
|
+
assert_forward_iteration( [[1, "100"], [2, "200"], [3, "300"]],
|
88
|
+
:delete_if,
|
89
|
+
:fdb )
|
90
|
+
end
|
91
|
+
|
92
|
+
#######
|
93
|
+
private
|
94
|
+
#######
|
95
|
+
|
96
|
+
def assert_forward_iteration(expected_order, iterator, option = nil)
|
97
|
+
remove_db_files
|
98
|
+
if option == :fdb
|
99
|
+
fdb do |db|
|
100
|
+
db.update(3 => 300, 1 => 100, 2 => 200)
|
101
|
+
actual_order = [ ]
|
102
|
+
db.send(iterator) do |*args|
|
103
|
+
actual_order << (args.size == 1 ? args.first : args)
|
104
|
+
end
|
105
|
+
assert_equal(expected_order, actual_order)
|
106
|
+
end
|
107
|
+
else
|
108
|
+
bdb(:cmpfunc => option) do |db|
|
109
|
+
db.update(:c => 3, :a => 1, :b => 2)
|
110
|
+
actual_order = [ ]
|
111
|
+
db.send(iterator) do |*args|
|
112
|
+
actual_order << (args.size == 1 ? args.first : args)
|
113
|
+
end
|
114
|
+
assert_equal(expected_order, actual_order)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def assert_reverse_iteration(expected_order, iterator)
|
120
|
+
assert_forward_iteration(expected_order, iterator, REVERSE_ORDER_CMPFUNC)
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module SharedBinaryData
|
2
|
+
def test_null_bytes_are_preserved_during_key_iteration
|
3
|
+
@db.each_key do |key|
|
4
|
+
assert_equal(@key, key)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_null_bytes_are_preserved_during_iteration
|
9
|
+
@db.each do |key, value|
|
10
|
+
assert_equal(@key, key)
|
11
|
+
assert_equal(@value, value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module SharedIteration
|
2
|
+
def test_each_key_iterates_over_all_keys_in_the_database
|
3
|
+
@db.each_key do |key|
|
4
|
+
@keys.delete(key)
|
5
|
+
end
|
6
|
+
assert(@keys.empty?, "All keys were not iterated over")
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_each_iterates_over_all_key_value_pairs_in_arrays
|
10
|
+
@db.each do |key_value_array|
|
11
|
+
assert_instance_of(Array, key_value_array)
|
12
|
+
assert_equal(2, key_value_array.size)
|
13
|
+
key, value = key_value_array
|
14
|
+
assert_equal(key * 2, value)
|
15
|
+
@keys.delete(key)
|
16
|
+
@values.delete(value)
|
17
|
+
end
|
18
|
+
assert( @keys.empty? && @values.empty?,
|
19
|
+
"All key/value pairs were not iterated over" )
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_the_arrays_passed_to_each_can_be_split
|
23
|
+
@db.each do |key, value|
|
24
|
+
@keys.delete(key)
|
25
|
+
@values.delete(value)
|
26
|
+
end
|
27
|
+
assert( @keys.empty? && @values.empty?,
|
28
|
+
"All key/value pairs were not iterated over" )
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_each_pair_is_an_alias_for_each
|
32
|
+
each_arrays = [ ]
|
33
|
+
@db.each do |array|
|
34
|
+
each_arrays << array
|
35
|
+
end
|
36
|
+
@db.each_pair do |array|
|
37
|
+
each_arrays.delete(array)
|
38
|
+
end
|
39
|
+
each_keys_and_values = [ ]
|
40
|
+
@db.each do |key, value|
|
41
|
+
each_keys_and_values << [key, value]
|
42
|
+
end
|
43
|
+
@db.each_pair do |key, value|
|
44
|
+
each_keys_and_values.delete([key, value])
|
45
|
+
end
|
46
|
+
assert( each_arrays.empty? && each_keys_and_values.empty?,
|
47
|
+
"The iterations did not match" )
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_each_value_iterates_over_all_values_in_the_database
|
51
|
+
@db.each_value do |value|
|
52
|
+
@values.delete(value)
|
53
|
+
end
|
54
|
+
assert(@values.empty?, "All values were not iterated over")
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_the_standard_iterators_are_supported
|
58
|
+
assert_kind_of(Enumerable, @db)
|
59
|
+
|
60
|
+
# examples
|
61
|
+
assert_equal(%w[b bb], @db.find { |_, value| value == "bb" })
|
62
|
+
assert_nil(@db.find { |_, value| value == "dd" })
|
63
|
+
assert_equal(%w[aaa bbb ccc], @db.map { |key, value| key + value }.sort)
|
64
|
+
assert( @db.any? { |_, value| value.include? "c" },
|
65
|
+
"A value was not found during iteration" )
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_delete_if_removes_all_keys_for_which_the_block_returns_true
|
69
|
+
@db.delete_if { |key, _| key != "a" }
|
70
|
+
assert_equal([%w[a aa]], @db.to_a)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_iterators_return_self_to_match_hash_interface
|
74
|
+
%w[each_key each each_pair each_value delete_if].each do |iterator|
|
75
|
+
assert_equal(@db, @db.send(iterator) { })
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_to_hash_converts_the_database_to_a_hash
|
80
|
+
assert_equal(Hash[*@keys.zip(@values).flatten], @db.to_hash)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_to_hash_keeps_a_default_object_by_default
|
84
|
+
@db.default = 0
|
85
|
+
assert_equal(0, @db.to_hash[:missing])
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_to_hash_keeps_a_default_proc_by_default
|
89
|
+
@db.default = lambda { |key| "is #{key}" }
|
90
|
+
assert_equal("is missing", @db.to_hash[:missing])
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_to_hash_can_be_told_to_ignore_a_default
|
94
|
+
@db.default = 0
|
95
|
+
assert_nil(@db.to_hash(false)[:missing])
|
96
|
+
@db.default = lambda { |key| "is #{key}" }
|
97
|
+
assert_nil(@db.to_hash(false)[:missing])
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module SharedTuning
|
2
|
+
def test_a_mutex_can_be_activated_as_the_database_is_created
|
3
|
+
assert_option_calls([:setmutex], :mutex => true)
|
4
|
+
end
|
5
|
+
|
6
|
+
def test_a_size_can_be_set_for_extra_mapped_memory
|
7
|
+
size = rand(1_000) + 1
|
8
|
+
assert_option_calls([:setxmsiz, size], :xmsiz => size)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_extra_mapped_memory_size_is_converted_to_an_int
|
12
|
+
assert_option_calls([:setxmsiz, 42], :xmsiz => "42")
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_a_step_unit_can_be_set_for_auto_defragmentation
|
16
|
+
unit = rand(1_000) + 1
|
17
|
+
assert_option_calls([:setdfunit, unit], :dfunit => unit)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_auto_defragmentation_step_unit_is_converted_to_an_int
|
21
|
+
assert_option_calls([:setdfunit, 42], :dfunit => "42")
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_nested_transactions_can_be_ignored
|
25
|
+
db(:nested_transactions => :ignore) do |db|
|
26
|
+
result = db.transaction {
|
27
|
+
db.transaction { # ignored
|
28
|
+
41
|
29
|
+
} + 1 # ignored
|
30
|
+
}
|
31
|
+
assert_equal(42, result)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_nested_transactions_can_be_set_to_fail_with_an_error
|
36
|
+
[:fail, :raise].each do |setting|
|
37
|
+
db(:nested_transactions => setting) do |db|
|
38
|
+
db.transaction do
|
39
|
+
assert_raise(OKMixer::Error::TransactionError) do
|
40
|
+
db.transaction { } # nested fails with error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_a_mode_string_can_be_passed
|
48
|
+
assert_raise(OKMixer::Error::CabinetError) do # file not found
|
49
|
+
db("r")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_the_mode_can_be_passed_as_as_option
|
54
|
+
assert_raise(OKMixer::Error::CabinetError) do # file not found
|
55
|
+
db(:mode => "r")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_an_option_mode_overrides_the_mode_argument_and_triggers_a_warning
|
60
|
+
warning = capture_stderr do
|
61
|
+
db("r", :mode => "wc") do
|
62
|
+
# just open and close
|
63
|
+
end
|
64
|
+
end
|
65
|
+
assert( !warning.empty?,
|
66
|
+
"A warning was not issued for an option mode with a mode argument" )
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_an_unknown_mode_triggers_a_warning
|
70
|
+
warning = capture_stderr do
|
71
|
+
db("wcu") do
|
72
|
+
# just open and close
|
73
|
+
end
|
74
|
+
end
|
75
|
+
assert(!warning.empty?, "A warning was not issued for an unknown mode")
|
76
|
+
end
|
77
|
+
|
78
|
+
#######
|
79
|
+
private
|
80
|
+
#######
|
81
|
+
|
82
|
+
def assert_option_calls(c_call, options)
|
83
|
+
args = capture_args(lib, c_call[0]) do
|
84
|
+
db(options) do
|
85
|
+
# just open and close
|
86
|
+
end
|
87
|
+
end
|
88
|
+
assert_instance_of(FFI::Pointer, args[0])
|
89
|
+
assert_equal(c_call[1..-1], args[1..-1])
|
90
|
+
end
|
91
|
+
end
|