perobs 4.0.0 → 4.1.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/lib/perobs.rb +1 -0
  3. data/lib/perobs/Array.rb +66 -19
  4. data/lib/perobs/BTree.rb +83 -12
  5. data/lib/perobs/BTreeBlob.rb +1 -1
  6. data/lib/perobs/BTreeDB.rb +2 -2
  7. data/lib/perobs/BTreeNode.rb +365 -85
  8. data/lib/perobs/BigArray.rb +267 -0
  9. data/lib/perobs/BigArrayNode.rb +998 -0
  10. data/lib/perobs/BigHash.rb +262 -0
  11. data/lib/perobs/BigTree.rb +184 -0
  12. data/lib/perobs/BigTreeNode.rb +873 -0
  13. data/lib/perobs/ConsoleProgressMeter.rb +61 -0
  14. data/lib/perobs/DataBase.rb +4 -3
  15. data/lib/perobs/DynamoDB.rb +57 -15
  16. data/lib/perobs/EquiBlobsFile.rb +143 -51
  17. data/lib/perobs/FNV_Hash_1a_64.rb +54 -0
  18. data/lib/perobs/FlatFile.rb +363 -203
  19. data/lib/perobs/FlatFileBlobHeader.rb +98 -54
  20. data/lib/perobs/FlatFileDB.rb +42 -20
  21. data/lib/perobs/Hash.rb +58 -13
  22. data/lib/perobs/IDList.rb +144 -0
  23. data/lib/perobs/IDListPage.rb +107 -0
  24. data/lib/perobs/IDListPageFile.rb +180 -0
  25. data/lib/perobs/IDListPageRecord.rb +142 -0
  26. data/lib/perobs/Object.rb +18 -15
  27. data/lib/perobs/ObjectBase.rb +38 -4
  28. data/lib/perobs/PersistentObjectCache.rb +53 -67
  29. data/lib/perobs/PersistentObjectCacheLine.rb +24 -12
  30. data/lib/perobs/ProgressMeter.rb +97 -0
  31. data/lib/perobs/SpaceTree.rb +21 -12
  32. data/lib/perobs/SpaceTreeNode.rb +53 -61
  33. data/lib/perobs/Store.rb +71 -32
  34. data/lib/perobs/version.rb +1 -1
  35. data/perobs.gemspec +4 -4
  36. data/test/Array_spec.rb +15 -6
  37. data/test/BTree_spec.rb +5 -2
  38. data/test/BigArray_spec.rb +214 -0
  39. data/test/BigHash_spec.rb +144 -0
  40. data/test/BigTreeNode_spec.rb +153 -0
  41. data/test/BigTree_spec.rb +259 -0
  42. data/test/EquiBlobsFile_spec.rb +105 -1
  43. data/test/FNV_Hash_1a_64_spec.rb +59 -0
  44. data/test/FlatFileDB_spec.rb +63 -14
  45. data/test/Hash_spec.rb +1 -2
  46. data/test/IDList_spec.rb +77 -0
  47. data/test/LegacyDBs/LegacyDB.rb +151 -0
  48. data/test/LegacyDBs/version_3/class_map.json +1 -0
  49. data/test/LegacyDBs/version_3/config.json +1 -0
  50. data/test/LegacyDBs/version_3/database.blobs +0 -0
  51. data/test/LegacyDBs/version_3/database_spaces.blobs +0 -0
  52. data/test/LegacyDBs/version_3/index.blobs +0 -0
  53. data/test/LegacyDBs/version_3/version +1 -0
  54. data/test/LockFile_spec.rb +9 -6
  55. data/test/SpaceTree_spec.rb +4 -1
  56. data/test/Store_spec.rb +290 -199
  57. data/test/spec_helper.rb +9 -4
  58. metadata +47 -10
  59. data/lib/perobs/TreeDB.rb +0 -277
@@ -0,0 +1,153 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
4
+ #
5
+ # MIT License
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'fileutils'
27
+
28
+ require 'spec_helper'
29
+ require 'perobs/Store'
30
+ require 'perobs/BigTree'
31
+
32
+ describe PEROBS::BigTreeNode do
33
+
34
+ before(:all) do
35
+ @db_name = generate_db_name(__FILE__)
36
+ @store = PEROBS::Store.new(@db_name)
37
+ @store['bigtree'] = @t = @store.new(PEROBS::BigTree, 4)
38
+ end
39
+
40
+ before(:each) do
41
+ @t.clear
42
+ end
43
+
44
+ after(:all) do
45
+ @store.delete_store
46
+ end
47
+
48
+ it 'should insert a key/value pair' do
49
+ n = @t.root
50
+ n.insert(0, 0)
51
+ expect(@t.check).to be true
52
+ s = @t.statistics
53
+ expect(s.leaf_nodes).to eql(1)
54
+ expect(s.branch_nodes).to eql(0)
55
+ expect(s.min_depth).to eql(1)
56
+ expect(s.max_depth).to eql(1)
57
+ node_chain = @t.node_chain(0)
58
+ expect(node_chain.size).to eql(1)
59
+ expect(node_chain.first).to eql(n)
60
+ end
61
+
62
+ it 'should split a leaf node that becomes full' do
63
+ 4.times { |n| @t.insert(n, n) }
64
+ expect(@t.check).to be true
65
+ s = @t.statistics
66
+ expect(s.leaf_nodes).to eql(1)
67
+ @t.insert(4, 4)
68
+ s = @t.statistics
69
+ expect(s.leaf_nodes).to eql(2)
70
+ expect(s.branch_nodes).to eql(1)
71
+ expect(s.min_depth).to eql(2)
72
+ expect(s.max_depth).to eql(2)
73
+ end
74
+
75
+ it 'should split a branch node that becomes full' do
76
+ 11.times { |n| @t.insert(n, n) }
77
+ s = @t.statistics
78
+ expect(s.leaf_nodes).to eql(5)
79
+ expect(s.branch_nodes).to eql(1)
80
+ expect(s.min_depth).to eql(2)
81
+ expect(s.max_depth).to eql(2)
82
+ @t.insert(11, 11)
83
+ expect(@t.check).to be true
84
+ s = @t.statistics
85
+ expect(s.leaf_nodes).to eql(5)
86
+ expect(s.branch_nodes).to eql(3)
87
+ expect(s.min_depth).to eql(3)
88
+ expect(s.max_depth).to eql(3)
89
+ end
90
+
91
+ it 'should merge leaf node with next sibling' do
92
+ 5.times { |n| @t.insert(n, n) }
93
+ expect(@t.check).to be true
94
+ s = @t.statistics
95
+ expect(s.leaf_nodes).to eql(2)
96
+
97
+ @t.remove(0)
98
+ expect(@t.check).to be true
99
+ s = @t.statistics
100
+ expect(s.leaf_nodes).to eql(1)
101
+ expect(s.min_depth).to eql(1)
102
+ expect(s.max_depth).to eql(1)
103
+ end
104
+
105
+ it 'should merge leaf node with previous siblin' do
106
+ 5.times { |n| @t.insert(n, n) }
107
+ expect(@t.check).to be true
108
+ s = @t.statistics
109
+ expect(s.leaf_nodes).to eql(2)
110
+
111
+ @t.remove(2)
112
+ @t.remove(3)
113
+ expect(@t.check).to be true
114
+ s = @t.statistics
115
+ expect(s.leaf_nodes).to eql(1)
116
+ end
117
+
118
+ it 'should merge branch node with next sibling' do
119
+ 12.times { |n| @t.insert(n, n) }
120
+ expect(@t.check).to be true
121
+ s = @t.statistics
122
+ expect(s.leaf_nodes).to eql(5)
123
+ expect(s.branch_nodes).to eql(3)
124
+
125
+ @t.remove(2)
126
+ @t.remove(3)
127
+ @t.remove(4)
128
+ @t.remove(5)
129
+ expect(@t.check).to be true
130
+ s = @t.statistics
131
+ expect(s.leaf_nodes).to eql(3)
132
+ expect(s.branch_nodes).to eql(1)
133
+ end
134
+
135
+ it 'should merge branch node with previous sibling' do
136
+ 12.times { |n| @t.insert(n, n) }
137
+ expect(@t.check).to be true
138
+ s = @t.statistics
139
+ expect(s.leaf_nodes).to eql(5)
140
+ expect(s.branch_nodes).to eql(3)
141
+
142
+ @t.remove(4)
143
+ @t.remove(5)
144
+ @t.remove(2)
145
+ @t.remove(3)
146
+ expect(@t.check).to be true
147
+ s = @t.statistics
148
+ expect(s.leaf_nodes).to eql(3)
149
+ expect(s.branch_nodes).to eql(1)
150
+ end
151
+
152
+ end
153
+
@@ -0,0 +1,259 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2016, 2017 by Chris Schlaeger <chris@taskjuggler.org>
4
+ #
5
+ # MIT License
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'fileutils'
27
+
28
+ require 'spec_helper'
29
+ require 'perobs/Store'
30
+ require 'perobs/BigTree'
31
+
32
+ describe PEROBS::BigTree do
33
+
34
+ ORDER = 7
35
+
36
+ before(:all) do
37
+ @db_name = generate_db_name(__FILE__)
38
+ @store = PEROBS::Store.new(@db_name)
39
+ @t = @store.new(PEROBS::BigTree, ORDER)
40
+ end
41
+
42
+ after(:all) do
43
+ @store.delete_store
44
+ end
45
+
46
+ it 'should be empty' do
47
+ expect(@t.empty?).to be true
48
+ expect(@t.length).to eql(0)
49
+ s = @t.statistics
50
+ expect(s.leaf_nodes).to eql(1)
51
+ expect(s.branch_nodes).to eql(0)
52
+ expect(s.min_depth).to eql(1)
53
+ expect(s.max_depth).to eql(1)
54
+ end
55
+
56
+ it 'should deal with requests for unknown keys' do
57
+ expect(@t.has_key?(42)).to be false
58
+ expect(@t.get(42)).to be_nil
59
+ end
60
+
61
+ it 'should support adding sequential key/value pairs' do
62
+ 0.upto(ORDER ** 3) do |i|
63
+ @t.insert(i, 3 * i)
64
+ expect(@t.check).to be true
65
+ expect(@t.length).to eql(i + 1)
66
+ expect(@t.has_key?(i)).to be true
67
+ expect(@t.get(i)).to eql(3 * i)
68
+ end
69
+ end
70
+
71
+ it 'should iterate over the stored key and value pairs' do
72
+ i = 0
73
+ @t.each do |k, v|
74
+ expect(k).to eql(i)
75
+ expect(v).to eql(3 * i)
76
+ i += 1
77
+ end
78
+ expect(i).to eql(ORDER ** 3 + 1)
79
+ end
80
+
81
+ it 'should iterate in reverse order over the stored key and value pairs' do
82
+ i = ORDER ** 3
83
+ @t.reverse_each do |k, v|
84
+ expect(k).to eql(i)
85
+ expect(v).to eql(3 * i)
86
+ i -= 1
87
+ end
88
+ expect(i).to eql(-1)
89
+ end
90
+
91
+ it 'should yield the key/value pairs on check' do
92
+ i = 0
93
+ @t.check do |k, v|
94
+ expect(k).to eql(k)
95
+ expect(v).to eql(3 * k)
96
+ i += 1
97
+ end
98
+ expect(i).to eql(ORDER ** 3 + 1)
99
+ end
100
+
101
+ it 'should support overwriting existing entries' do
102
+ 0.upto(ORDER ** 3) do |i|
103
+ @t.insert(i, 7 * i)
104
+ expect(@t.check).to be true
105
+ expect(@t.length).to eql(ORDER ** 3 + 1)
106
+ expect(@t.has_key?(i)).to be true
107
+ expect(@t.get(i)).to eql(7 * i)
108
+ end
109
+ end
110
+
111
+ it 'should support clearing the tree' do
112
+ @t.clear
113
+ expect(@t.check).to be true
114
+ expect(@t.empty?).to be true
115
+ expect(@t.length).to eql(0)
116
+ i = 0
117
+ @t.each { |k, v| i += 1 }
118
+ expect(i).to eql(0)
119
+ end
120
+
121
+ it 'should support adding random key/value pairs' do
122
+ (1..ORDER ** 3).to_a.shuffle.each do |i|
123
+ @t.insert(i, i * 100)
124
+ end
125
+ expect(@t.check).to be true
126
+ (1..ORDER ** 3).to_a.shuffle.each do |i|
127
+ expect(@t.get(i)).to eql(i * 100)
128
+ end
129
+ end
130
+
131
+ it 'should support removing keys in random order' do
132
+ @t.clear
133
+ (1..ORDER ** 3).to_a.shuffle.each do |i|
134
+ @t.insert(i, i * 100)
135
+ end
136
+ expect(@t.length).to eql(ORDER ** 3)
137
+ (1..ORDER ** 3).to_a.shuffle.each do |i|
138
+ expect(@t.remove(i)).to eql(i * 100)
139
+ expect(@t.check).to be true
140
+ end
141
+ expect(@t.length).to eql(0)
142
+ end
143
+
144
+ it 'should support removing keys in increasing order' do
145
+ @t.clear
146
+ (1..ORDER ** 3).to_a.shuffle.each do |i|
147
+ @t.insert(i, i * 100)
148
+ end
149
+ expect(@t.length).to eql(ORDER ** 3)
150
+ (1..ORDER ** 3).to_a.each do |i|
151
+ expect(@t.remove(i)).to eql(i * 100)
152
+ expect(@t.check).to be true
153
+ end
154
+ expect(@t.length).to eql(0)
155
+ end
156
+
157
+ it 'should support removing keys in reverse order' do
158
+ @t.clear
159
+ (1..ORDER ** 3).to_a.shuffle.each do |i|
160
+ @t.insert(i, i * 100)
161
+ end
162
+ expect(@t.length).to eql(ORDER ** 3)
163
+ (1..ORDER ** 3).to_a.reverse_each do |i|
164
+ expect(@t.remove(i)).to eql(i * 100)
165
+ expect(@t.check).to be true
166
+ end
167
+ expect(@t.length).to eql(0)
168
+ end
169
+
170
+ it 'should persist the data' do
171
+ db_name = generate_db_name(__FILE__ + '_persist')
172
+ store = PEROBS::Store.new(db_name)
173
+ store['bigtree'] = t = store.new(PEROBS::BigTree, 4)
174
+ 10.times do |i|
175
+ t.insert(i, i)
176
+ end
177
+ 10.times do |i|
178
+ expect(t.get(i)).to eql(i)
179
+ end
180
+ store.exit
181
+
182
+ store = PEROBS::Store.new(db_name)
183
+ t = store['bigtree']
184
+ 10.times do |i|
185
+ expect(t.get(i)).to eql(i)
186
+ end
187
+ store.delete_store
188
+ end
189
+
190
+ it 'should delete all entries matching a condition' do
191
+ @t.clear
192
+ (1..50).to_a.shuffle.each do |i|
193
+ @t.insert(i, i)
194
+ end
195
+ @t.delete_if { |k, v| v % 7 == 0 }
196
+ expect(@t.check).to be true
197
+ @t.each do |k, v|
198
+ expect(v % 7).to be > 0, "failed for #{v}"
199
+ end
200
+ expect(@t.length).to eql(43)
201
+ @t.delete_if { |k, v| v % 2 == 0 }
202
+ expect(@t.check).to be true
203
+ @t.each do |k, v|
204
+ expect(v % 2).to be > 0
205
+ end
206
+ expect(@t.length).to eql(21)
207
+ @t.delete_if { |k, v| true }
208
+ expect(@t.check).to be true
209
+ expect(@t.empty?).to be true
210
+ end
211
+
212
+ it 'should survive a real-world usage test' do
213
+ @t.clear
214
+ ref = {}
215
+ 0.upto(1000) do
216
+ case rand(5)
217
+ when 0
218
+ 0.upto(2) do
219
+ key = rand(100000)
220
+ value = key * 10
221
+ @t.insert(key, value)
222
+ ref[key] = value
223
+ end
224
+ when 1
225
+ if ref.length > 0
226
+ key = ref.keys[rand(ref.keys.length)]
227
+ expect(@t.remove(key)).to eql(ref[key])
228
+ ref.delete(key)
229
+ end
230
+ when 2
231
+ if ref.length > 0
232
+ 0.upto(3) do
233
+ key = ref.keys[rand(ref.keys.length)]
234
+ expect(@t.get(key)).to eql(ref[key])
235
+ end
236
+ end
237
+ when 3
238
+ if ref.length > 0
239
+ key = ref.keys[rand(ref.keys.length)]
240
+ value = ref[key] + 1
241
+ @t.insert(key, value)
242
+ ref[key] = value
243
+ end
244
+ when 4
245
+ if rand(50) == 0
246
+ expect(@t.check).to be true
247
+ end
248
+ end
249
+ end
250
+
251
+ i = 0
252
+ @t.each do |k, v|
253
+ expect(ref[k]).to eql(v)
254
+ i += 1
255
+ end
256
+ expect(i).to eql(ref.length)
257
+ end
258
+
259
+ end
@@ -27,13 +27,17 @@ require 'fileutils'
27
27
 
28
28
  require 'spec_helper'
29
29
  require 'perobs/EquiBlobsFile'
30
+ require 'perobs/ProgressMeter'
30
31
 
31
32
  describe PEROBS::EquiBlobsFile do
32
33
 
33
34
  before(:all) do
35
+ PEROBS.log.level = Logger::ERROR
36
+ PEROBS.log.open($stderr)
34
37
  @db_dir = generate_db_name('EquiBlobsFile')
35
38
  FileUtils.mkdir_p(@db_dir)
36
- @bf = PEROBS::EquiBlobsFile.new(@db_dir, 'EquiBlobsFile', 8)
39
+ @bf = PEROBS::EquiBlobsFile.new(@db_dir, 'EquiBlobsFile',
40
+ PEROBS::ProgressMeter.new, 8)
37
41
  end
38
42
 
39
43
  after(:all) do
@@ -134,6 +138,12 @@ describe PEROBS::EquiBlobsFile do
134
138
  expect(@bf.check).to be true
135
139
  end
136
140
 
141
+ it 'should support deleting reserved blobs' do
142
+ adr = @bf.free_address
143
+ @bf.delete_blob(adr)
144
+ expect(@bf.check).to be true
145
+ end
146
+
137
147
  it 'should support clearing the file' do
138
148
  @bf.clear
139
149
  expect(@bf.total_entries).to eql(0)
@@ -191,5 +201,99 @@ describe PEROBS::EquiBlobsFile do
191
201
  expect(@bf.check).to be true
192
202
  end
193
203
 
204
+ it 'should support custom offsets' do
205
+ @bf.close
206
+ @bf.erase
207
+ @bf.clear_custom_data
208
+ @bf.register_custom_data('foo', 42)
209
+ @bf.register_custom_data('bar', 43)
210
+ @bf.open
211
+ expect(@bf.total_entries).to eql(0)
212
+ expect(@bf.total_spaces).to eql(0)
213
+ expect(@bf.check).to be true
214
+ expect(@bf.free_address).to eql(1)
215
+ @bf.store_blob(1,'11111111')
216
+ expect(@bf.free_address).to eql(2)
217
+ @bf.store_blob(2,'22222222')
218
+ expect(@bf.free_address).to eql(3)
219
+ @bf.store_blob(3,'33333333')
220
+ expect(@bf.check).to be true
221
+ expect(@bf.total_entries).to eql(3)
222
+ expect(@bf.total_spaces).to eql(0)
223
+ @bf.delete_blob(2)
224
+ expect(@bf.check).to be true
225
+ expect(@bf.total_entries).to eql(2)
226
+ expect(@bf.total_spaces).to eql(1)
227
+ expect(@bf.free_address).to eql(2)
228
+ @bf.store_blob(2,'44444444')
229
+ expect(@bf.total_entries).to eql(3)
230
+ expect(@bf.total_spaces).to eql(0)
231
+ expect(@bf.check).to be true
232
+ end
233
+
234
+ it 'should support a mix of adds and deletes' do
235
+ @bf.close
236
+ @bf.erase
237
+ @bf.clear_custom_data
238
+ @bf.register_custom_data('foo', 42)
239
+ @bf.register_custom_data('bar', 43)
240
+ @bf.open
241
+
242
+ entries = {}
243
+ 1000.times do |i|
244
+ rand(30).times do
245
+ adr = @bf.free_address
246
+ expect(entries[adr]).to be nil
247
+ val = rand(2 ** 64)
248
+ @bf.store_blob(adr, [ val ].pack('Q'))
249
+ entries[adr] = val
250
+ #expect(@bf.check).to be true
251
+ end
252
+
253
+ rand(15).times do
254
+ unless entries.empty?
255
+ addresses = entries.keys
256
+ adr = addresses[rand(addresses.length)]
257
+ expect(@bf.retrieve_blob(adr).unpack('Q').first).to eql(entries[adr])
258
+ @bf.delete_blob(adr)
259
+ entries.delete(adr)
260
+ #expect(@bf.check).to be true
261
+ end
262
+ end
263
+
264
+ rand(5).times do
265
+ unless entries.empty?
266
+ addresses = entries.keys
267
+ adr = addresses[rand(addresses.length)]
268
+ val = rand(2 ** 64)
269
+ @bf.store_blob(adr, [ val ].pack('Q'))
270
+ entries[adr] = val
271
+ #expect(@bf.check).to be true
272
+ end
273
+ end
274
+
275
+ if rand(100) == 0
276
+ expect(@bf.check).to be true
277
+ end
278
+
279
+ if rand(100) == 0
280
+ @bf.first_entry = i
281
+ @bf.set_custom_data('foo', i)
282
+ end
283
+
284
+ if rand(50) == 0
285
+ @bf.close
286
+ @bf.open
287
+ end
288
+
289
+ if rand(500) == 0
290
+ @bf.clear
291
+ entries = {}
292
+ end
293
+ end
294
+
295
+ expect(@bf.check).to be true
296
+ end
297
+
194
298
  end
195
299