perobs 3.0.1 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +19 -18
  3. data/lib/perobs.rb +2 -0
  4. data/lib/perobs/Array.rb +68 -21
  5. data/lib/perobs/BTree.rb +110 -54
  6. data/lib/perobs/BTreeBlob.rb +14 -13
  7. data/lib/perobs/BTreeDB.rb +11 -10
  8. data/lib/perobs/BTreeNode.rb +551 -197
  9. data/lib/perobs/BTreeNodeCache.rb +10 -8
  10. data/lib/perobs/BTreeNodeLink.rb +11 -1
  11. data/lib/perobs/BigArray.rb +285 -0
  12. data/lib/perobs/BigArrayNode.rb +1002 -0
  13. data/lib/perobs/BigHash.rb +246 -0
  14. data/lib/perobs/BigTree.rb +197 -0
  15. data/lib/perobs/BigTreeNode.rb +873 -0
  16. data/lib/perobs/Cache.rb +47 -22
  17. data/lib/perobs/ClassMap.rb +2 -2
  18. data/lib/perobs/ConsoleProgressMeter.rb +61 -0
  19. data/lib/perobs/DataBase.rb +4 -3
  20. data/lib/perobs/DynamoDB.rb +62 -20
  21. data/lib/perobs/EquiBlobsFile.rb +174 -59
  22. data/lib/perobs/FNV_Hash_1a_64.rb +54 -0
  23. data/lib/perobs/FlatFile.rb +536 -242
  24. data/lib/perobs/FlatFileBlobHeader.rb +120 -84
  25. data/lib/perobs/FlatFileDB.rb +58 -27
  26. data/lib/perobs/FuzzyStringMatcher.rb +175 -0
  27. data/lib/perobs/Hash.rb +129 -35
  28. data/lib/perobs/IDList.rb +144 -0
  29. data/lib/perobs/IDListPage.rb +107 -0
  30. data/lib/perobs/IDListPageFile.rb +180 -0
  31. data/lib/perobs/IDListPageRecord.rb +142 -0
  32. data/lib/perobs/LockFile.rb +3 -0
  33. data/lib/perobs/Object.rb +28 -20
  34. data/lib/perobs/ObjectBase.rb +53 -10
  35. data/lib/perobs/PersistentObjectCache.rb +142 -0
  36. data/lib/perobs/PersistentObjectCacheLine.rb +99 -0
  37. data/lib/perobs/ProgressMeter.rb +97 -0
  38. data/lib/perobs/SpaceManager.rb +273 -0
  39. data/lib/perobs/SpaceTree.rb +63 -47
  40. data/lib/perobs/SpaceTreeNode.rb +134 -115
  41. data/lib/perobs/SpaceTreeNodeLink.rb +1 -1
  42. data/lib/perobs/StackFile.rb +1 -1
  43. data/lib/perobs/Store.rb +180 -70
  44. data/lib/perobs/version.rb +1 -1
  45. data/perobs.gemspec +4 -4
  46. data/test/Array_spec.rb +48 -39
  47. data/test/BTreeDB_spec.rb +2 -2
  48. data/test/BTree_spec.rb +50 -1
  49. data/test/BigArray_spec.rb +261 -0
  50. data/test/BigHash_spec.rb +152 -0
  51. data/test/BigTreeNode_spec.rb +153 -0
  52. data/test/BigTree_spec.rb +259 -0
  53. data/test/EquiBlobsFile_spec.rb +105 -5
  54. data/test/FNV_Hash_1a_64_spec.rb +59 -0
  55. data/test/FlatFileDB_spec.rb +199 -15
  56. data/test/FuzzyStringMatcher_spec.rb +261 -0
  57. data/test/Hash_spec.rb +27 -16
  58. data/test/IDList_spec.rb +77 -0
  59. data/test/LegacyDBs/LegacyDB.rb +155 -0
  60. data/test/LegacyDBs/version_3/class_map.json +1 -0
  61. data/test/LegacyDBs/version_3/config.json +1 -0
  62. data/test/LegacyDBs/version_3/database.blobs +0 -0
  63. data/test/LegacyDBs/version_3/database_spaces.blobs +0 -0
  64. data/test/LegacyDBs/version_3/index.blobs +0 -0
  65. data/test/LegacyDBs/version_3/version +1 -0
  66. data/test/LockFile_spec.rb +9 -6
  67. data/test/Object_spec.rb +5 -5
  68. data/test/SpaceManager_spec.rb +176 -0
  69. data/test/SpaceTree_spec.rb +27 -9
  70. data/test/Store_spec.rb +353 -206
  71. data/test/perobs_spec.rb +7 -3
  72. data/test/spec_helper.rb +9 -4
  73. metadata +59 -16
  74. data/lib/perobs/SpaceTreeNodeCache.rb +0 -76
  75. data/lib/perobs/TreeDB.rb +0 -277
@@ -1,4 +1,4 @@
1
1
  module PEROBS
2
2
  # The version number
3
- VERSION = "3.0.1"
3
+ VERSION = "4.3.0"
4
4
  end
data/perobs.gemspec CHANGED
@@ -16,9 +16,9 @@ GEM_SPEC = Gem::Specification.new do |spec|
16
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
- spec.required_ruby_version = '>=2.0'
19
+ spec.required_ruby_version = '>=2.4'
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.6'
22
- spec.add_development_dependency 'yard', '~>0.8.7'
23
- spec.add_development_dependency 'rake', '~> 10.0'
21
+ spec.add_development_dependency 'bundler', '~> 2.3'
22
+ spec.add_development_dependency 'yard', '~>0.9.12'
23
+ spec.add_development_dependency 'rake', '~> 12.3.3'
24
24
  end
data/test/Array_spec.rb CHANGED
@@ -33,7 +33,7 @@ require 'perobs'
33
33
 
34
34
  class PO < PEROBS::Object
35
35
 
36
- po_attr :name
36
+ attr_persist :name
37
37
 
38
38
  def initialize(store, name = nil)
39
39
  super(store)
@@ -65,7 +65,7 @@ describe PEROBS::Array do
65
65
  @store.transaction do
66
66
  @store['b'] = @store.new(PEROBS::Array)
67
67
  end
68
- @store.sync
68
+ @store.exit
69
69
  @store = nil
70
70
  GC.start
71
71
 
@@ -85,7 +85,7 @@ describe PEROBS::Array do
85
85
  expect(a[0]).to eq('A')
86
86
  expect(a[1]).to eq('B')
87
87
  expect(a[2].name).to eq('foobar')
88
- @store.sync
88
+ @store.exit
89
89
 
90
90
  @store = PEROBS::Store.new(@db_name)
91
91
  a = @store['a']
@@ -102,7 +102,7 @@ describe PEROBS::Array do
102
102
  vs = ''
103
103
  a.each { |v| vs << v }
104
104
  expect(vs).to eq('ABC')
105
- @store.sync
105
+ @store.exit
106
106
 
107
107
  @store = PEROBS::Store.new(@db_name)
108
108
  a = @store['a']
@@ -113,15 +113,15 @@ describe PEROBS::Array do
113
113
  end
114
114
 
115
115
  # Utility method to create a PEROBS::Array from a normal Array.
116
- def cpa(ary = nil)
116
+ def cpa(ary = nil, id = 'a')
117
117
  a = @store.new(PEROBS::Array)
118
118
  a.replace(ary) unless ary.nil?
119
- @store['a'] = a
119
+ @store[id] = a
120
120
  end
121
121
 
122
122
  def pcheck
123
123
  yield
124
- @store.sync
124
+ @store.exit
125
125
  @store = PEROBS::Store.new(@db_name)
126
126
  yield
127
127
  end
@@ -147,44 +147,54 @@ describe PEROBS::Array do
147
147
  it 'should support re-writing methods' do
148
148
  x = cpa([2, 5, 3, 1, 7])
149
149
  x.sort!{ |a, b| a <=> b }
150
- pcheck { expect(x).to eq([ 1, 2, 3, 5, 7 ]) }
151
- x.sort!{ |a, b| b - a }
152
- pcheck { expect(x).to eq([ 7, 5, 3, 2, 1 ]) }
150
+ pcheck { expect(@store['a']).to eq([ 1, 2, 3, 5, 7 ]) }
151
+ @store['a'].sort!{ |a, b| b - a }
152
+ pcheck { expect(@store['a']).to eq([ 7, 5, 3, 2, 1 ]) }
153
153
 
154
- x.clear
155
- pcheck { expect(x).to eq([]) }
154
+ @store['a'].clear
155
+ pcheck { expect(@store['a']).to eq([]) }
156
156
  end
157
157
 
158
158
  it 'should support <<()' do
159
159
  a = cpa([ 0, 1, 2 ])
160
160
  a << 4
161
- pcheck { expect(a).to eq([ 0, 1, 2, 4 ]) }
161
+ pcheck { expect(@store['a']).to eq([ 0, 1, 2, 4 ]) }
162
162
  end
163
163
 
164
164
  it 'should support []=' do
165
165
  a = cpa([ 0, nil, 2 ])
166
166
  a[1] = 1
167
- pcheck { expect(a).to eq([ 0, 1, 2 ]) }
167
+ pcheck { expect(@store['a']).to eq([ 0, 1, 2 ]) }
168
168
  end
169
169
 
170
170
  it 'should support collect!()' do
171
171
  a = cpa([ 1, 'cat', 1..1 ])
172
- expect(a.collect! { |e| e.class }).to eq([ Fixnum, String, Range ])
173
- pcheck { expect(a).to eq([ Fixnum, String, Range ]) }
172
+ if RUBY_VERSION < '2.2'
173
+ expect(a.collect! { |e| e.class.to_s }.to_a).to eq([ 'Fixnum', 'String', 'Range' ])
174
+ pcheck { expect(@store['a'].to_a).to eq([ 'Fixnum', 'String', 'Range' ]) }
175
+ else
176
+ expect(a.collect! { |e| e.class.to_s }.to_a).to eq([ 'Integer', 'String', 'Range' ])
177
+ pcheck { expect(@store['a'].to_a).to eq([ 'Integer', 'String', 'Range' ]) }
178
+ end
174
179
 
175
180
  a = cpa([ 1, 'cat', 1..1 ])
176
181
  expect(a.collect! { 99 }).to eq([ 99, 99, 99])
177
- pcheck { expect(a).to eq([ 99, 99, 99]) }
182
+ pcheck { expect(@store['a']).to eq([ 99, 99, 99]) }
178
183
  end
179
184
 
180
185
  it 'should support map!()' do
181
186
  a = cpa([ 1, 'cat', 1..1 ])
182
- expect(a.map! { |e| e.class }).to eq([ Fixnum, String, Range ])
183
- pcheck { expect(a).to eq([ Fixnum, String, Range ]) }
187
+ if RUBY_VERSION < '2.2'
188
+ expect(a.map! { |e| e.class.to_s }.to_a).to eq([ 'Fixnum', 'String', 'Range' ])
189
+ pcheck { expect(@store['a'].to_a).to eq([ 'Fixnum', 'String', 'Range' ]) }
190
+ else
191
+ expect(a.map! { |e| e.class.to_s }.to_a).to eq([ 'Integer', 'String', 'Range' ])
192
+ pcheck { expect(@store['a'].to_a).to eq([ 'Integer', 'String', 'Range' ]) }
193
+ end
184
194
 
185
195
  a = cpa([ 1, 'cat', 1..1 ])
186
196
  expect(a.map! { 99 }).to eq([ 99, 99, 99])
187
- pcheck { expect(a).to eq ([ 99, 99, 99]) }
197
+ pcheck { expect(@store['a']).to eq ([ 99, 99, 99]) }
188
198
  end
189
199
 
190
200
  it 'should support fill()' do
@@ -194,39 +204,39 @@ describe PEROBS::Array do
194
204
  end
195
205
 
196
206
  it 'should support flatten!()' do
197
- a1 = cpa([ 1, 2, 3])
198
- a2 = cpa([ 5, 6 ])
199
- a3 = cpa([ 4, a2 ])
200
- a4 = cpa([ a1, a3 ])
201
- pcheck { expect(a4.flatten).to eq([ 1, 2, 3, 4, 5, 6 ]) }
207
+ a1 = cpa([ 1, 2, 3], 'a1')
208
+ a2 = cpa([ 5, 6 ], 'a2')
209
+ a3 = cpa([ 4, a2 ], 'a3')
210
+ a4 = cpa([ a1, a3 ], 'a4')
211
+ pcheck { expect(@store['a4'].flatten).to eq([ 1, 2, 3, 4, 5, 6 ]) }
202
212
  end
203
213
 
204
214
  it 'should support replace()' do
205
- a = cpa([ 1, 2, 3])
206
- a_id = a.__id__
207
- expect(a.replace(cpa([4, 5, 6]))).to eq([ 4, 5, 6 ])
208
- pcheck { expect(a).to eq ([ 4, 5, 6 ]) }
215
+ a1 = cpa([ 1, 2, 3], 'a1')
216
+ a_id = a1.__id__
217
+ expect(a1.replace(cpa([4, 5, 6], 'a2'))).to eq([ 4, 5, 6 ])
218
+ pcheck { expect(@store['a1']).to eq ([ 4, 5, 6 ]) }
209
219
  end
210
220
 
211
221
  it 'should support insert()' do
212
222
  a = cpa([ 0 ])
213
223
  a.insert(1)
214
- pcheck { expect(a).to eq([ 0 ]) }
215
- a.insert(1, 1)
216
- pcheck { expect(a).to eq([ 0, 1]) }
224
+ pcheck { expect(@store['a']).to eq([ 0 ]) }
225
+ @store['a'].insert(1, 1)
226
+ pcheck { expect(@store['a']).to eq([ 0, 1]) }
217
227
  end
218
228
 
219
229
  it 'should support push()' do
220
230
  a = cpa([ 1, 2, 3 ])
221
231
  a.push(4, 5)
222
- pcheck { expect(a).to eq([ 1, 2, 3, 4, 5 ]) }
223
- a.push(nil)
224
- pcheck { expect(a).to eq([ 1, 2, 3, 4, 5, nil ]) }
232
+ pcheck { expect(@store['a']).to eq([ 1, 2, 3, 4, 5 ]) }
233
+ @store['a'].push(nil)
234
+ pcheck { expect(@store['a']).to eq([ 1, 2, 3, 4, 5, nil ]) }
225
235
  end
226
236
 
227
237
  it 'should support inspect' do
228
- a1 = cpa([ 1 ])
229
- a2 = cpa([ 1, a1 ])
238
+ a1 = cpa([ 1 ], 'a1')
239
+ a2 = cpa([ 1, a1 ], 'a2')
230
240
  expect(a1.inspect).to eq("<PEROBS::Array:#{a1._id}>\n[\n 1\n]\n")
231
241
  expect(a2.inspect).to eq("<PEROBS::Array:#{a2._id}>\n[\n 1,\n <PEROBS::ObjectBase:#{a1._id}>\n]\n")
232
242
  end
@@ -242,9 +252,8 @@ describe PEROBS::Array do
242
252
  it 'should catch a leaked PEROBS::ObjectBase object' do
243
253
  @store['a'] = a = @store.new(PEROBS::Array)
244
254
  o = @store.new(PO)
245
- a[0] = o.get_self
246
255
  PEROBS.log.open(StringIO.new)
247
- expect { @store.sync }.to raise_error(PEROBS::FatalError)
256
+ expect { a[0] = o.get_self }.to raise_error(PEROBS::FatalError)
248
257
  PEROBS.log.open($stderr)
249
258
  end
250
259
 
data/test/BTreeDB_spec.rb CHANGED
@@ -56,7 +56,7 @@ describe PEROBS::BTreeDB do
56
56
  expect(@db.include?(0)).to be false
57
57
  h = {
58
58
  'String' => 'What god has wrought',
59
- 'Fixnum' => 42,
59
+ 'Integer' => 42,
60
60
  'Float' => 3.14,
61
61
  'True' => true,
62
62
  'False' => false,
@@ -75,7 +75,7 @@ describe PEROBS::BTreeDB do
75
75
  expect(@db.include?(0)).to be false
76
76
  h = {
77
77
  'String' => 'What god has wrought',
78
- 'Fixnum' => 42,
78
+ 'Integer' => 42,
79
79
  'Float' => 3.14,
80
80
  'True' => true,
81
81
  'False' => false,
data/test/BTree_spec.rb CHANGED
@@ -27,13 +27,16 @@ require 'fileutils'
27
27
 
28
28
  require 'spec_helper'
29
29
  require 'perobs/BTree'
30
+ require 'perobs/ProgressMeter'
30
31
 
31
32
  describe PEROBS::BTree do
32
33
 
33
34
  before(:all) do
34
35
  @db_dir = generate_db_name('BTree')
35
36
  FileUtils.mkdir_p(@db_dir)
36
- @m = PEROBS::BTree.new(@db_dir, 'btree', 11)
37
+ @m = PEROBS::BTree.new(@db_dir, 'btree', 11, PEROBS::ProgressMeter.new)
38
+ PEROBS.log.level = Logger::ERROR
39
+ PEROBS.log.open($stderr)
37
40
  end
38
41
 
39
42
  after(:all) do
@@ -48,6 +51,7 @@ describe PEROBS::BTree do
48
51
  @m.open
49
52
  expect(@m.to_s).to eql("o--- @1\n")
50
53
  #expect(@m.to_a).to eql([])
54
+ expect(@m.check).to be true
51
55
  end
52
56
 
53
57
  it 'should support adding sequential key/value pairs' do
@@ -125,4 +129,49 @@ describe PEROBS::BTree do
125
129
  end
126
130
  end
127
131
 
132
+ it 'should survive a real-world usage test' do
133
+ @m.clear
134
+ ref = {}
135
+ 0.upto(20000) do
136
+ case rand(5)
137
+ when 0
138
+ 0.upto(2) do
139
+ key = rand(100000)
140
+ value = rand(10000000)
141
+ @m.insert(key, value)
142
+ ref[key] = value
143
+ end
144
+ when 1
145
+ if ref.length > 0
146
+ key = ref.keys[rand(ref.keys.length)]
147
+ expect(@m.remove(key)).to eql(ref[key])
148
+ ref.delete(key)
149
+ end
150
+ when 2
151
+ if ref.length > 0
152
+ 0.upto(3) do
153
+ key = ref.keys[rand(ref.keys.length)]
154
+ expect(@m.get(key)).to eql(ref[key])
155
+ end
156
+ end
157
+ when 3
158
+ if ref.length > 0
159
+ key = ref.keys[rand(ref.keys.length)]
160
+ value = rand(10000000)
161
+ @m.insert(key, value)
162
+ ref[key] = value
163
+ end
164
+ when 4
165
+ if rand(50) == 0
166
+ expect(@m.check).to be true
167
+ end
168
+ when 5
169
+ if rand(50) == 0
170
+ @m.close
171
+ @m.open
172
+ end
173
+ end
174
+ end
175
+ end
176
+
128
177
  end
@@ -0,0 +1,261 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Copyright (c) 2015, 2016 by Chris Schlaeger <chris@taskjuggler.org>
4
+ #
5
+ # This file contains tests for Array that are similar to the tests for the
6
+ # Array implementation in MRI. The ideas of these tests were replicated in
7
+ # this code.
8
+ #
9
+ # MIT License
10
+ #
11
+ # Permission is hereby granted, free of charge, to any person obtaining
12
+ # a copy of this software and associated documentation files (the
13
+ # "Software"), to deal in the Software without restriction, including
14
+ # without limitation the rights to use, copy, modify, merge, publish,
15
+ # distribute, sublicense, and/or sell copies of the Software, and to
16
+ # permit persons to whom the Software is furnished to do so, subject to
17
+ # the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be
20
+ # included in all copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
+
30
+ require 'spec_helper'
31
+
32
+ require 'perobs'
33
+ require 'perobs/BigArray'
34
+
35
+ NODE_ENTRIES = 6
36
+
37
+ describe PEROBS::BigArray do
38
+
39
+ before(:all) do
40
+ @db_name = generate_db_name(__FILE__)
41
+ @store = PEROBS::Store.new(@db_name)
42
+ end
43
+
44
+ before(:each) do
45
+ @store['array'] = @a = @store.new(PEROBS::BigArray, NODE_ENTRIES)
46
+ end
47
+
48
+ after(:each) do
49
+ @store['array'] = @a = nil
50
+ @store.gc
51
+ end
52
+
53
+ after(:all) do
54
+ @store.delete_store
55
+ end
56
+
57
+ it 'should be empty on create' do
58
+ expect(@a.empty?).to be true
59
+ expect(@a.length).to eq(0)
60
+ expect(@a.check).to be true
61
+ expect(@a[0]).to be nil
62
+ expect(@a.first).to be nil
63
+ expect(@a.last).to be nil
64
+ end
65
+
66
+ it 'should append the first element' do
67
+ @a << 0
68
+ expect(@a.empty?).to be false
69
+ expect(@a[0]).to eq(0)
70
+ expect(@a.first).to eq(0)
71
+ expect(@a.last).to eq(0)
72
+ expect(@a.length).to eq(1)
73
+ expect(@a.check).to be true
74
+ end
75
+
76
+ it 'should fill 10 nodes with appends' do
77
+ (10 * NODE_ENTRIES).times do |i|
78
+ @a << i
79
+ expect(@a.check).to be true
80
+ expect(@a.length).to eq(i + 1)
81
+ end
82
+ expect(@a.first).to eq(0)
83
+ expect(@a.last).to eq(10 * NODE_ENTRIES - 1)
84
+ end
85
+
86
+ it 'should insert at 0' do
87
+ @a.insert(0, 0)
88
+ expect(@a.empty?).to be false
89
+ end
90
+
91
+ it 'should insert at end' do
92
+ 0.upto(3 * NODE_ENTRIES) do |i|
93
+ @a.insert(i, i)
94
+ expect(@a.check).to be true
95
+ expect(@a.length).to eq(i + 1)
96
+ end
97
+ end
98
+
99
+ it 'should insert in the middle' do
100
+ 0.upto(NODE_ENTRIES - 1) do |i|
101
+ @a << 9999
102
+ end
103
+ 0.upto(3 * NODE_ENTRIES) do |i|
104
+ @a.insert(i, i)
105
+ expect(@a.check).to be true
106
+ expect(@a.length).to eq(i + 1 + NODE_ENTRIES)
107
+ end
108
+ end
109
+
110
+ it 'should convert to a Ruby Array' do
111
+ expect(@a.to_a).to eql([])
112
+ (3 * NODE_ENTRIES).times do |i|
113
+ @a << i
114
+ end
115
+ expect(@a.to_a).to eql((0..3 * NODE_ENTRIES - 1).to_a)
116
+ end
117
+
118
+ it 'should support the [] operator' do
119
+ expect(@a[0]).to be nil
120
+ expect(@a[-1]).to be nil
121
+ @a[0] = 0
122
+ expect(@a[0]).to eq(0)
123
+ 1.upto(3 * NODE_ENTRIES) do |i|
124
+ @a.insert(i, i)
125
+ end
126
+ 0.upto(3 * NODE_ENTRIES) do |i|
127
+ expect(@a[i]).to eq(i)
128
+ end
129
+ expect(@a[3 * NODE_ENTRIES + 1]).to be nil
130
+ 0.upto(3 * NODE_ENTRIES) do |i|
131
+ expect(@a[-3 * NODE_ENTRIES + i - 1]).to eq(i)
132
+ end
133
+ expect(@a[-3 * NODE_ENTRIES - 2]).to be nil
134
+ (3 * NODE_ENTRIES + 1).upto(4 * NODE_ENTRIES) do |i|
135
+ expect(@a[i]).to be nil
136
+ end
137
+ end
138
+
139
+ it 'should delete elements' do
140
+ expect(@a.delete_at(0)).to be nil
141
+ expect(@a.length).to eq(0)
142
+ expect(@a.check).to be true
143
+ expect(@a.delete_at(-1)).to be nil
144
+ expect(@a.length).to eq(0)
145
+ expect(@a.check).to be true
146
+ @a << 0
147
+ expect(@a.delete_at(0)).to eql(0)
148
+ expect(@a.length).to eq(0)
149
+ expect(@a.check).to be true
150
+
151
+ n = 5 * NODE_ENTRIES
152
+ 0.upto(n) { |i| @a.insert(i, i) }
153
+ 0.upto(n) do |i|
154
+ expect(@a.delete_at(0)).to eql(i)
155
+ expect(@a.check).to be true
156
+ end
157
+
158
+ 0.upto(n) { |i| @a.insert(i, i) }
159
+ n.downto(0) do |i|
160
+ expect(@a.delete_at(-1)).to eql(i)
161
+ expect(@a.check).to be true
162
+ end
163
+
164
+ n = 15 * NODE_ENTRIES
165
+ 0.upto(n - 1) { |i| @a.insert(i, i) }
166
+ expect(@a.delete_at(n + 2)).to be nil
167
+ expect(@a.delete_at(-(n + 2))).to be nil
168
+ expect(@a.size).to eql(n)
169
+
170
+ n.times do |i|
171
+ idx = rand(@a.size)
172
+ @a.delete_at(idx)
173
+ expect(@a.size).to be (n - 1 - i)
174
+ expect(@a.check).to be true
175
+ end
176
+ expect(@a.size).to eql(0)
177
+ end
178
+
179
+ it 'should fill the gaps' do
180
+ 1.upto(4) do |i|
181
+ idx = i * NODE_ENTRIES * NODE_ENTRIES
182
+ @a[idx] = idx
183
+ expect(@a[idx - 1]).to be nil
184
+ expect(@a[idx + 1]).to be nil
185
+ expect(@a.check).to be true
186
+ end
187
+ expect(@a[0]).to be nil
188
+ end
189
+
190
+ it 'should insert after a gap' do
191
+ ref = []
192
+ 10.times do |i|
193
+ idx = 10 + i * 3
194
+ @a[idx] = idx
195
+ ref[idx] = idx
196
+ expect(@a[idx]).to eql(idx)
197
+ expect(@a.check).to be true
198
+ end
199
+ 10.times do |i|
200
+ idx = i * 5
201
+ @a[idx] = idx
202
+ ref[idx] = idx
203
+ expect(@a[idx]).to eql(idx)
204
+ expect(@a.check).to be true
205
+ end
206
+ expect(@a.check).to be true
207
+ expect(@a.to_a).to eql(ref)
208
+ end
209
+
210
+ it 'should iterate over all values' do
211
+ n = 3 * NODE_ENTRIES
212
+ 0.upto(n) { |i| @a.insert(i, i) }
213
+
214
+ i = 0
215
+ @a.each do |v|
216
+ expect(v).to eql(i)
217
+ i += 1
218
+ end
219
+ end
220
+
221
+ it 'should iterate over all values in reverse order' do
222
+ n = 3 * NODE_ENTRIES
223
+ 0.upto(n) { |i| @a.insert(i, i) }
224
+
225
+ i = 0
226
+ @a.reverse_each do |v|
227
+ expect(v).to eql(n - i)
228
+ i += 1
229
+ end
230
+ end
231
+
232
+ it 'should insert at the beginning' do
233
+ (5 * NODE_ENTRIES).downto(0) do |i|
234
+ @a.insert(0, i)
235
+ end
236
+ expect(@a.check).to be true
237
+ a = Array.new(5 * NODE_ENTRIES + 1) { |i| i }
238
+ expect(@a.to_a).to eq(a)
239
+ end
240
+
241
+ it 'should persist the data' do
242
+ db_name = generate_db_name(__FILE__ + "_persist")
243
+ store = PEROBS::Store.new(db_name)
244
+ store['array'] = a = store.new(PEROBS::BigArray, NODE_ENTRIES)
245
+
246
+ (3 * NODE_ENTRIES).times do |i|
247
+ a.insert(i, i)
248
+ end
249
+ expect(a.length).to eq(3 * NODE_ENTRIES)
250
+ store.exit
251
+
252
+ store = PEROBS::Store.new(db_name)
253
+ a = store['array']
254
+ (3 * NODE_ENTRIES).times do |i|
255
+ expect(a[i]).to eql(i)
256
+ end
257
+ expect(a.length).to eq(3 * NODE_ENTRIES)
258
+ store.delete_store
259
+ end
260
+
261
+ end