rocksdb-ruby 0.2.3 → 1.0.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.
@@ -4,26 +4,54 @@ require "rocksdb"
4
4
 
5
5
  describe RocksDB do
6
6
  before do
7
- @rocksdb = RocksDB::DB.new "/tmp/file2"
8
- @rocksdb.put("test:multi_db", "1")
7
+ @rocksdb = RocksDB.open temp_db_path
8
+ @rocksdb.put("test", "value")
9
9
  @rocksdb.close
10
-
11
- @rocksdb2 = RocksDB::DB.new("/tmp/file2", {:readonly => true})
12
10
  end
13
11
 
14
- it 'should get data' do
15
- expect{@rocksdb2.put("test:multi_db", "10")}.to raise_error(RuntimeError)
16
- expect{@rocksdb2.delete("test:multi_db")}.to raise_error(RuntimeError)
17
- expect(@rocksdb2.get("test:multi_db")).to eq "1"
18
- expect(@rocksdb2.is_readonly?).to eq true
19
-
20
- batch = RocksDB::Batch.new
21
- batch.delete("test:batch1")
22
- batch.put("test:batch2", "b")
23
- expect{@rocksdb2.write(batch)}.to raise_error(RuntimeError)
12
+ context "when writable" do
13
+ before do
14
+ @rocksdb = RocksDB.open temp_db_path
15
+ end
16
+
17
+ it 'writable? is true' do
18
+ expect(@rocksdb.writable?).to eq true
19
+ end
20
+
21
+ it 'can write' do
22
+ expect{@rocksdb.put("newtest", "value")}
23
+ .not_to raise_error
24
+ end
25
+
26
+ it 'can read' do
27
+ expect(@rocksdb.get("test")).to eq "value"
28
+ end
29
+
30
+ after do
31
+ @rocksdb.close
32
+ end
24
33
  end
25
34
 
26
- after do
27
- @rocksdb2.close
35
+ context "when not writable" do
36
+ before do
37
+ @rocksdb = RocksDB.open_readonly temp_db_path
38
+ end
39
+
40
+ it 'writable? is false' do
41
+ expect(@rocksdb.writable?).to eq false
42
+ end
43
+
44
+ it "can't write" do
45
+ expect{@rocksdb.put("newtest", "value")}
46
+ .to raise_error(RocksDB::ReadOnly)
47
+ end
48
+
49
+ it 'can read' do
50
+ expect(@rocksdb.get("test")).to eq "value"
51
+ end
52
+
53
+ after do
54
+ @rocksdb.close
55
+ end
28
56
  end
29
57
  end
@@ -4,183 +4,250 @@ require "rocksdb"
4
4
  require 'fileutils'
5
5
 
6
6
  describe RocksDB do
7
- before :all do
8
- FileUtils.rm(Dir.glob('/tmp/file/*'))
9
- end
7
+ warn "RocksDB library version: #{RocksDB::library_version}" rescue nil
10
8
 
11
9
  before do
12
- @rocksdb = RocksDB::DB.new("/tmp/file")
10
+ @rocksdb = RocksDB.open(temp_db_path)
13
11
  end
14
12
 
15
- it "should get property" do
16
- @rocksdb.put("test:read", "1")
17
- expect(@rocksdb.property("rocksdb.estimate-num-keys")).to eq("1")
18
- end
13
+ context "close" do
14
+ it 'closes database' do
15
+ @rocksdb.close
16
+ expect(@rocksdb.open?).to eq false
17
+ end
19
18
 
20
- it 'should get data' do
21
- @rocksdb.put("test:read", "1")
22
- expect(@rocksdb.is_readonly?).to eq false
23
- expect(@rocksdb.get("test:read")).to eq "1"
24
- end
19
+ it 'not fails to close database that is already closes' do
20
+ @rocksdb.close
21
+ @rocksdb.close
22
+ expect(@rocksdb.open?).to eq false
23
+ end
25
24
 
26
- it 'should put data' do
27
- expect(@rocksdb.put("test:put", "2")).to be true
28
- expect(@rocksdb.get("test:put")).to eq "2"
25
+ it 'raises exception on closed database' do
26
+ @rocksdb.close
27
+
28
+ expect{ @rocksdb.get "test" }
29
+ .to raise_error(RocksDB::DatabaseClosed)
30
+ expect{ @rocksdb.put "test", "value" }
31
+ .to raise_error(RocksDB::DatabaseClosed)
32
+ end
29
33
  end
30
34
 
31
- it 'should delete data' do
32
- @rocksdb.put("test:delete", "3")
33
- expect(@rocksdb.get("test:delete")).to eq "3"
35
+ context "get_one" do
36
+ it 'should get data' do
37
+ @rocksdb.put("test:read", "1")
38
+ expect(@rocksdb.get_one("test:read")).to eq "1"
39
+ end
34
40
 
35
- expect(@rocksdb.delete("test:delete")).to be true
36
- expect(@rocksdb.get("test:delete")).to be_nil
41
+ it 'should get with []' do
42
+ @rocksdb.delete("test:hash")
43
+ expect(@rocksdb["test:hash"]).to be_nil
44
+ @rocksdb.put("test:hash", "42")
45
+ expect(@rocksdb["test:hash"]).to eq "42"
46
+ end
47
+
48
+ it 'should return nil if not found' do
49
+ expect(@rocksdb.get_one("must_not_be_found")).to be_nil
50
+ end
37
51
  end
38
52
 
39
- it 'should get multi data' do
40
- @rocksdb.put("test:multi1", "a")
41
- @rocksdb.put("test:multi2", "b")
42
- @rocksdb.put("test:multi3", "c")
53
+ context "get_many" do
54
+ before do
55
+ @rocksdb.put("test:multi1", "a")
56
+ @rocksdb.put("test:multi2", "b")
57
+ @rocksdb.put("test:multi3", "c")
58
+ end
59
+
60
+ it 'should get all values' do
61
+ expect(@rocksdb.get_many(["test:multi1", "test:multi2", "test:multi3"]))
62
+ .to eq ["a", "b", "c"]
63
+ end
64
+
65
+ it 'should return nil if key not found' do
66
+ @rocksdb.delete("test:multi2")
43
67
 
44
- expect(@rocksdb.multi_get(["test:multi1", "test:multi2", "test:multi3"])).to eq ["a", "b", "c"]
68
+ expect(@rocksdb.get_many(["test:multi1", "test:multi2", "test:multi3"]))
69
+ .to eq ["a", nil, "c"]
70
+ end
45
71
  end
46
72
 
47
- it 'should put data atomic update' do
48
- @rocksdb.put("test:batch1", "a")
49
- @rocksdb.delete("test:batch2")
73
+ context "get" do
74
+ before do
75
+ @rocksdb.put("test:multi1", "a")
76
+ @rocksdb.put("test:multi2", "b")
77
+ @rocksdb.put("test:multi3", "c")
78
+ end
50
79
 
51
- expect(@rocksdb.get("test:batch1")).to eq "a"
52
- expect(@rocksdb.get("test:batch")).to be_nil
80
+ it 'should get one, when one argument' do
81
+ expect(@rocksdb.get("test:multi2"))
82
+ .to eq "b"
83
+ end
53
84
 
54
- batch = RocksDB::Batch.new
55
- batch.delete("test:batch1")
56
- batch.put("test:batch2", "b")
57
- @rocksdb.write(batch)
85
+ it 'should get many, when two or more arguments' do
86
+ expect(@rocksdb.get("test:multi1", "test:multi2", "test:multi3"))
87
+ .to eq ["a", "b", "c"]
88
+ end
58
89
 
59
- expect(@rocksdb.get("test:batch1")).to be_nil
60
- expect(@rocksdb.get("test:batch2")).to eq "b"
90
+ it 'should get many, when array given' do
91
+ expect(@rocksdb.get(["test:multi1", "test:multi2", "test:multi3"]))
92
+ .to eq ["a", "b", "c"]
93
+ end
61
94
  end
62
95
 
63
- it 'should use multiple db' do
64
- @rocksdb2 = RocksDB::DB.new("/tmp/file2")
65
- @rocksdb.put("test:multi_db", "1")
66
- @rocksdb2.put("test:multi_db", "2")
67
-
68
- expect(@rocksdb.get("test:multi_db")).to eq "1"
69
- expect(@rocksdb2.get("test:multi_db")).to eq "2"
70
- @rocksdb2.close
71
- end
96
+ context "put" do
97
+ it 'should put data' do
98
+ expect(@rocksdb.put("test:put", "2")).to be true
99
+ expect(@rocksdb.get("test:put")).to eq "2"
100
+ end
72
101
 
73
- it 'should use japanese charactor' do
74
- @rocksdb.put("test:japanese", "あいうえお")
102
+ it 'should overwrite data with put' do
103
+ expect(@rocksdb.put("test:put", "2")).to be true
104
+ expect(@rocksdb.get("test:put")).to eq "2"
75
105
 
76
- expect(@rocksdb.get("test:japanese")).to eq "あいうえお"
77
- expect(@rocksdb.multi_get(["test:japanese"])).to eq ["あいうえお"]
78
- end
106
+ expect(@rocksdb.put("test:put", "3")).to be true
107
+ expect(@rocksdb.get("test:put")).to eq "3"
108
+ end
79
109
 
80
- it 'should use each' do
81
- iter = @rocksdb.each
110
+ it 'should put any data that can behave like string' do
111
+ class CastableTest
112
+ def initialize(value)
113
+ @value = value
114
+ end
82
115
 
83
- array = []
84
- @rocksdb.each do |value|
85
- expect(value).not_to be_empty
86
- array << value
116
+ def to_str
117
+ @value.to_s
118
+ end
119
+ end
120
+
121
+ castable_key = CastableTest.new(42)
122
+ castable_value = CastableTest.new([1984])
123
+
124
+ expect(@rocksdb.put(castable_key, castable_value)).to be true
125
+ expect(@rocksdb.get("42")).to eq "[1984]"
87
126
  end
88
127
 
89
- rev_array = []
90
- @rocksdb.reverse_each do |value|
91
- expect(value).not_to be_empty
92
- rev_array << value
128
+ it "should gracefully fail on non-string objects" do
129
+ expect{ @rocksdb.put(42, true) }.to raise_error(TypeError)
93
130
  end
94
-
95
131
 
96
- expect(array).to eq rev_array.reverse
132
+ it 'should put data atomic update' do
133
+ @rocksdb.put("test:batch1", "a")
134
+ @rocksdb.delete("test:batch2")
135
+
136
+ expect(@rocksdb.get("test:batch1")).to eq "a"
137
+ expect(@rocksdb.get("test:batch")).to be_nil
97
138
 
98
- @rocksdb.each_index do |key|
99
- expect(key).not_to be_empty
139
+ batch = RocksDB::Batch.new
140
+ batch.delete("test:batch1")
141
+ batch.put("test:batch2", "b")
142
+ @rocksdb.write(batch)
143
+
144
+ expect(@rocksdb.get("test:batch1")).to be_nil
145
+ expect(@rocksdb.get("test:batch2")).to eq "b"
100
146
  end
101
147
 
102
- @rocksdb.each_with_index do |key, value|
103
- expect(key).not_to be_empty
104
- expect(value).not_to be_empty
148
+ it 'should put and read multibyte data' do
149
+ @rocksdb.put("test:japanese", "あいうえお")
150
+ @rocksdb.put("test:russian", "Перепёлка")
151
+
152
+ expect(@rocksdb.get("test:japanese")).to eq "あいうえお"
153
+ expect(@rocksdb.get("test:japanese", "test:russian"))
154
+ .to eq ["あいうえお", "Перепёлка"]
105
155
  end
106
156
 
107
- iter.close
157
+ it 'should put with []=' do
158
+ @rocksdb.delete("test:hash")
159
+ expect(@rocksdb["test:hash"]).to be_nil
160
+ @rocksdb["test:hash"] = "a"
161
+ expect(@rocksdb.get("test:hash")).to eq "a"
162
+ end
108
163
  end
109
164
 
110
- it 'should exists?' do
111
- @rocksdb.put("test:exists?", "a")
112
- @rocksdb.delete("test:noexists?")
113
- expect(@rocksdb.exists?("test:exists?")).to be true
114
- expect(@rocksdb.exists?("test:noexists?")).to be false
165
+ context "exists?" do
166
+ it 'returns true when exists' do
167
+ @rocksdb.put "test:exists?", "a"
168
+
169
+ expect(@rocksdb.exists?("test:exists?")).to be true
170
+ expect(@rocksdb.includes?("test:exists?")).to be true
171
+ end
172
+
173
+ it 'returns false when no exists' do
174
+ expect(@rocksdb.exists?("test:noexists?")).to be false
175
+ expect(@rocksdb.includes?("test:noexists?")).to be false
176
+ end
115
177
 
116
- expect(@rocksdb.includes?("test:exists?")).to be true
117
- expect(@rocksdb.includes?("test:noexists?")).to be false
178
+ it 'returns false when key deleted' do
179
+ @rocksdb.put "test:deleted_key", "deleted_value"
180
+ @rocksdb.delete "test:deleted_key"
118
181
 
182
+ expect(@rocksdb.exists?("test:deleted_key")).to be false
183
+ expect(@rocksdb.includes?("test:deleted_key")).to be false
184
+ end
119
185
  end
120
186
 
121
- it 'hash' do
122
- @rocksdb.delete("test:hash")
123
- expect(@rocksdb["test:hash"]).to be_nil
124
- @rocksdb["test:hash"] = "a"
125
- expect(@rocksdb["test:hash"]).to eq "a"
187
+ context "delete" do
188
+ it 'should delete data' do
189
+ @rocksdb.put("test:delete", "3")
190
+ expect(@rocksdb.get("test:delete")).to eq "3"
126
191
 
192
+ expect(@rocksdb.delete("test:delete")).to be true
193
+ expect(@rocksdb.get("test:delete")).to be_nil
194
+ end
195
+
196
+ it 'should return true even if key does not exists' do
197
+ @rocksdb.delete("must_not_be_found_to_delete")
198
+ expect(@rocksdb.delete("must_not_be_found_to_delete")).to be true
199
+ end
200
+ end
201
+
202
+ it "should get property" do
203
+ @rocksdb.put("test:read", "1")
204
+ expect(@rocksdb.property("rocksdb.estimate-num-keys")).to eq("1")
205
+ end
206
+
207
+ it "should get library_version" do
208
+ expect(RocksDB.library_version).to match(/\d+\.\d+\.\d+/)
209
+ end
210
+
211
+ it 'should use multiple db' do
212
+ @rocksdb2 = RocksDB::DB.new("/tmp/file2")
213
+ @rocksdb.put("test:multi_db", "1")
214
+ @rocksdb2.put("test:multi_db", "2")
215
+
216
+ expect(@rocksdb.get("test:multi_db")).to eq "1"
217
+ expect(@rocksdb2.get("test:multi_db")).to eq "2"
218
+ @rocksdb2.close
127
219
  end
128
220
 
129
221
  it 'race condition test' do
130
222
  key = "test"
131
223
  value = "1"
132
224
 
133
- expect{RocksDB::DB.new("/tmp/file")}.to raise_error(RocksDB::DBError)
225
+ expect{RocksDB.open(temp_db_path)}.to raise_error(RocksDB::Error)
134
226
 
135
227
  expect(@rocksdb.put("test:put", "1")).to be true
136
228
 
137
- @rocksdb2 = RocksDB::DB.new("/tmp/file", {:readonly => true})
138
- expect(@rocksdb2.is_readonly?).to eq true
229
+ @rocksdb2 = RocksDB.open_readonly(temp_db_path)
230
+ expect(@rocksdb2.writable?).to eq false
139
231
  expect(@rocksdb2.get("test:put")).to eq "1"
140
232
 
141
233
  @rocksdb.close
142
234
 
143
- expect(@rocksdb.is_open?).to eq false
235
+ expect(@rocksdb.open?).to eq false
144
236
 
145
- @rocksdb = RocksDB::DB.new("/tmp/file")
146
- expect(@rocksdb.is_readonly?).to eq false
147
- expect(@rocksdb.is_open?).to eq true
237
+ @rocksdb = RocksDB.open(temp_db_path)
238
+ expect(@rocksdb.writable?).to eq true
239
+ expect(@rocksdb.open?).to eq true
148
240
  expect(@rocksdb.put("test:put", "2")).to be true
149
-
150
- @rocksdb3 = RocksDB::DB.new("/tmp/file", {:readonly => true})
151
- expect(@rocksdb3.is_readonly?).to eq true
152
- expect(@rocksdb3.is_open?).to eq true
241
+
242
+ @rocksdb3 = RocksDB.open_readonly(temp_db_path)
243
+ expect(@rocksdb3.writable?).to eq false
244
+ expect(@rocksdb3.open?).to eq true
153
245
  expect(@rocksdb3.get("test:put")).to eq "2"
154
246
 
155
247
  @rocksdb2.close
156
248
  @rocksdb3.close
157
-
158
249
  end
159
-
160
- it 'singleton' do
161
- @rocksdb2 = RocksDB::DB.get_instance("/tmp/file")
162
- expect(@rocksdb2.is_readonly?).to eq false
163
- expect(@rocksdb2.is_open?).to eq true
164
-
165
- @rocksdb3 = RocksDB::DB.get_instance("/tmp/file")
166
- expect(@rocksdb3.is_readonly?).to eq false
167
- expect(@rocksdb).to eq (@rocksdb3)
168
- expect(@rocksdb2).to eq (@rocksdb3)
169
-
170
- @rocksdb4 = RocksDB::DB.get_instance("/tmp/file", {:readonly => true})
171
- expect(@rocksdb2).not_to eq (@rocksdb4)
172
- expect(@rocksdb4.is_readonly?).to eq true
173
- expect(@rocksdb4.is_open?).to eq true
174
-
175
- @rocksdb2.close
176
- expect{@rocksdb2.get("test:put")}.to raise_error(RuntimeError)
177
- expect(@rocksdb2.is_open?).to eq false
178
- expect{@rocksdb3.get("test:put")}.to raise_error(RuntimeError)
179
- expect(@rocksdb3.is_open?).to eq false
180
250
 
181
- @rocksdb4.close
182
- end
183
-
184
251
  context 'compact' do
185
252
  it 'works with no parameters' do
186
253
  expect(@rocksdb.compact).to eq(true)
@@ -203,4 +270,3 @@ describe RocksDB do
203
270
  @rocksdb.close
204
271
  end
205
272
  end
206
-
@@ -2,38 +2,325 @@
2
2
  require 'spec_helper'
3
3
  require "RocksDB"
4
4
 
5
- describe RocksDB do
5
+ describe RocksDB::Iterator do
6
6
  before do
7
- @rocksdb = RocksDB::DB.new "/tmp/file"
7
+ @rocksdb = RocksDB.open temp_db_path
8
+
9
+ @rocksdb.put("test1:0001", "a")
10
+ @rocksdb.put("test1:0002", "b")
11
+ @rocksdb.put("test1:0003", "c")
12
+ @rocksdb.put("test1:0004", "d")
13
+ @rocksdb.put("test1:0005", "e")
14
+
15
+ @iterator = @rocksdb.to_iterator
16
+ end
17
+
18
+ context "valid" do
19
+ it 'should be valid at start' do
20
+ @iterator.seek_to_first
21
+
22
+ expect(@iterator).to be_valid
23
+ end
24
+
25
+ it 'should not be valid at end' do
26
+ @iterator.seek_to_last
27
+ @iterator.next
28
+
29
+ expect(@iterator).to_not be_valid
30
+ end
31
+
32
+ it 'should not be valid when closed' do
33
+ @iterator.close
34
+
35
+ expect(@iterator).to_not be_valid
36
+ end
37
+
38
+ it 'should not be valid when database closed' do
39
+ @rocksdb.close
40
+
41
+ expect(@iterator).to_not be_valid
42
+ end
43
+ end
44
+
45
+ context 'close' do
46
+ it 'closes iterator' do
47
+ @iterator.close
48
+ expect(@iterator).to_not be_valid
49
+ end
50
+
51
+ it 'raises exception on closed iterator' do
52
+ @iterator.close
53
+ expect{@iterator.seek_to_first}.to raise_error(RocksDB::IteratorClosed)
54
+ end
55
+
56
+ it 'raises exception on closed database' do
57
+ @rocksdb.close
58
+ expect{@iterator.seek_to_first}.to raise_error(RocksDB::DatabaseClosed)
59
+ end
60
+ end
61
+
62
+ context "enumerable" do
63
+ context "each" do
64
+ it 'iterates over all values' do
65
+ values = []
66
+
67
+ @rocksdb.each do |value|
68
+ values << value
69
+ end
70
+
71
+ expect(values).to eq ["a", "b", "c", "d", "e"]
72
+ end
73
+
74
+ it 'returns enumerable' do
75
+ expect(@rocksdb.each)
76
+ .to be_a(Enumerable)
77
+ end
78
+ end
79
+
80
+ context "reverse_each" do
81
+ it 'iterates over all values in reverse order' do
82
+ values = []
83
+
84
+ @rocksdb.reverse_each do |value|
85
+ values << value
86
+ end
87
+
88
+ expect(values).to eq ["e", "d", "c", "b", "a"]
89
+ end
90
+
91
+ it 'returns enumerable' do
92
+ expect(@rocksdb.reverse_each)
93
+ .to be_a(Enumerable)
94
+ end
95
+ end
96
+
97
+ context "each_key" do
98
+ it 'iterates over all keys' do
99
+ keys = []
100
+
101
+ @rocksdb.each_key do |key|
102
+ keys << key
103
+ end
104
+
105
+ expect(keys).to eq [
106
+ "test1:0001",
107
+ "test1:0002",
108
+ "test1:0003",
109
+ "test1:0004",
110
+ "test1:0005"
111
+ ]
112
+ end
113
+
114
+ it 'returns enumerable' do
115
+ expect(@rocksdb.each_key)
116
+ .to be_a(Enumerable)
117
+ end
118
+ end
119
+
120
+ context "reverse_each_key" do
121
+ it 'iterates over all keys in reverse order' do
122
+ keys = []
123
+
124
+ @rocksdb.reverse_each_key do |key|
125
+ keys << key
126
+ end
127
+
128
+ expect(keys).to eq [
129
+ "test1:0005",
130
+ "test1:0004",
131
+ "test1:0003",
132
+ "test1:0002",
133
+ "test1:0001"
134
+ ]
135
+ end
136
+
137
+ it 'returns enumerable' do
138
+ expect(@rocksdb.reverse_each_key)
139
+ .to be_a(Enumerable)
140
+ end
141
+ end
142
+
143
+ context "each_pair" do
144
+ it 'iterates over all values and keys' do
145
+ pairs = {}
146
+
147
+ @rocksdb.each_pair do |key, value|
148
+ pairs[key] = value
149
+ end
150
+
151
+ expect(pairs).to eq ({
152
+ "test1:0001"=>"a",
153
+ "test1:0002"=>"b",
154
+ "test1:0003"=>"c",
155
+ "test1:0004"=>"d",
156
+ "test1:0005"=>"e"
157
+ })
158
+ end
159
+
160
+ it 'returns enumerable' do
161
+ expect(@rocksdb.each_pair)
162
+ .to be_a(Enumerable)
163
+ end
164
+ end
165
+
166
+ context "reverse_each_pair" do
167
+ it 'iterates over all values and keys in reverse order' do
168
+ pairs = {}
169
+
170
+ @rocksdb.reverse_each_pair do |key, value|
171
+ pairs[key] = value
172
+ end
173
+
174
+ expect(pairs).to eq ({
175
+ "test1:0005"=>"e",
176
+ "test1:0004"=>"d",
177
+ "test1:0003"=>"c",
178
+ "test1:0002"=>"b",
179
+ "test1:0001"=>"a"
180
+ })
181
+ end
182
+
183
+ it 'returns enumerable' do
184
+ expect(@rocksdb.reverse_each_pair)
185
+ .to be_a(Enumerable)
186
+ end
187
+ end
188
+
189
+ context "each_prefix" do
190
+ it 'iterates over keys and values of given prefix' do
191
+ @rocksdb.put("test0:0000", "z")
192
+ @rocksdb.put("test2:0000", "u")
193
+ result = {}
194
+
195
+ @rocksdb.each_prefix("test1") do |key, value|
196
+ result[key] = value
197
+ end
198
+
199
+ expect(result).to eq({
200
+ "test1:0001" => "a",
201
+ "test1:0002" => "b",
202
+ "test1:0003" => "c",
203
+ "test1:0004" => "d",
204
+ "test1:0005" => "e",
205
+ })
206
+ end
207
+
208
+ it 'returns enumerable' do
209
+ expect(@rocksdb.each_prefix("test1"))
210
+ .to be_a(Enumerable)
211
+ end
212
+ end
213
+
214
+ context "each_range" do
215
+ it 'iterates over keys and values of given range' do
216
+ @rocksdb.put("test0:0001", "-1")
217
+ @rocksdb.put("test2:multi3", "f")
218
+
219
+ result = {}
220
+
221
+ @rocksdb.each_range("test1:0002", "test1:0004") do |key, value|
222
+ result[key] = value
223
+ end
224
+
225
+ expect(result).to eq({
226
+ "test1:0002" => "b",
227
+ "test1:0003" => "c",
228
+ "test1:0004" => "d"
229
+ })
230
+ end
231
+
232
+ it 'returns enumerable' do
233
+ expect(@rocksdb.each_range("test1:0002", "test1:0004"))
234
+ .to be_a(Enumerable)
235
+ end
236
+ end
237
+ end
238
+
239
+ it 'should seek to first' do
240
+ @iterator.seek_to_first
241
+
242
+ expect(@iterator.key).to eq "test1:0001"
243
+ expect(@iterator.value).to eq "a"
244
+ end
245
+
246
+ it 'should seek to last' do
247
+ @iterator.seek_to_last
248
+
249
+ expect(@iterator.key).to eq "test1:0005"
250
+ expect(@iterator.value).to eq "e"
251
+ end
252
+
253
+ context "seek" do
254
+ it 'should seek to record when record exists' do
255
+ @iterator.seek "test1:0003"
256
+
257
+ expect(@iterator.key).to eq "test1:0003"
258
+ expect(@iterator.value).to eq "c"
259
+ end
260
+
261
+ it 'should seek to first' do
262
+ @iterator.seek "alpha"
263
+
264
+ expect(@iterator).to be_valid
265
+ expect(@iterator.key).to eq "test1:0001"
266
+ expect(@iterator.value).to eq "a"
267
+ end
8
268
  end
9
269
 
10
- it 'should use iterator' do
11
- iterator = @rocksdb.new_iterator
270
+ context "seek_for_previous",
271
+ skip: !RocksDB::Iterator.instance_methods.include?(:seek_for_previous) do
12
272
 
13
- iterator.seek_to_first
14
-
15
- expect(iterator.valid).to be true
16
- while(iterator.valid)
17
- expect(iterator.value).not_to be_empty
18
- expect(iterator.key).not_to be_empty
19
- iterator.next
273
+ it 'should seek to record when target record exists' do
274
+ @iterator.seek_for_previous "test1:0004"
275
+
276
+ expect(@iterator.key).to eq "test1:0004"
277
+ expect(@iterator.value).to eq "d"
278
+ end
279
+
280
+ it 'should seek to closest record when target is not exists' do
281
+ @iterator.seek_for_previous "test2"
282
+
283
+ expect(@iterator.key).to eq "test1:0005"
284
+ expect(@iterator.value).to eq "e"
20
285
  end
21
- iterator.close
22
286
  end
23
287
 
24
- it 'should seek iterator' do
25
- iterator = @rocksdb.new_iterator
288
+ it 'should go forward' do
289
+ @iterator.seek_to_first
290
+ @iterator.next
291
+
292
+ expect(@iterator.key).to eq "test1:0002"
293
+ expect(@iterator.value).to eq "b"
294
+ end
26
295
 
27
- iterator.seek("test:put")
28
-
29
- iterator.valid
30
- expect(iterator.value).to eq "2"
31
- expect(iterator.key).to eq "test:put"
296
+ it 'should go back' do
297
+ @iterator.seek_to_last
298
+ @iterator.previous
299
+
300
+ expect(@iterator.key).to eq "test1:0004"
301
+ expect(@iterator.value).to eq "d"
302
+ end
303
+
304
+ it 'should iterate all the way to the end' do
305
+ result = {}
306
+ @iterator.seek_to_first
307
+
308
+ while @iterator.valid?
309
+ result[@iterator.key] = @iterator.value
310
+ @iterator.next
311
+ end
32
312
 
33
- iterator.close
313
+ expect(result).to eq ({
314
+ "test1:0001" => "a",
315
+ "test1:0002" => "b",
316
+ "test1:0003" => "c",
317
+ "test1:0004" => "d",
318
+ "test1:0005" => "e"
319
+ })
34
320
  end
35
321
 
36
322
  after do
323
+ @iterator.close
37
324
  @rocksdb.close
38
325
  end
39
326
  end