corestore 6.0.0-beta2 → 6.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.
- package/.github/workflows/test-node.yml +4 -5
- package/README.md +59 -2
- package/index.js +330 -79
- package/package.json +15 -25
- package/test/all.js +255 -223
- package/test/cache.js +46 -0
- package/test/helpers/index.js +2 -7
- package/lib/buffer-file.js +0 -26
- package/lib/db.js +0 -160
- package/lib/errors.js +0 -44
- package/lib/loader.js +0 -287
- package/lib/pending-file.js +0 -37
- package/lib/replicator.js +0 -66
package/test/all.js
CHANGED
|
@@ -1,302 +1,334 @@
|
|
|
1
|
-
const
|
|
1
|
+
const test = require('brittle')
|
|
2
|
+
const crypto = require('hypercore-crypto')
|
|
2
3
|
const ram = require('random-access-memory')
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const OldCorestore = require('@andrewosh/corestore-migration')
|
|
4
|
+
const os = require('os')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const b4a = require('b4a')
|
|
7
|
+
const sodium = require('sodium-universal')
|
|
8
8
|
|
|
9
9
|
const Corestore = require('..')
|
|
10
|
-
const { cleanup } = require('./helpers')
|
|
11
10
|
|
|
12
|
-
test('
|
|
13
|
-
const store =
|
|
11
|
+
test('basic get with caching', async function (t) {
|
|
12
|
+
const store = new Corestore(ram)
|
|
13
|
+
const core1a = store.get({ name: 'core-1' })
|
|
14
|
+
const core1b = store.get({ name: 'core-1' })
|
|
15
|
+
const core2 = store.get({ name: 'core-2' })
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
const core1 = store.get({ name: 'default' })
|
|
17
|
-
await toPromises(core1).ready()
|
|
17
|
+
await Promise.all([core1a.ready(), core1b.ready(), core2.ready()])
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const core = store.get(core1.key)
|
|
22
|
-
await toPromises(core).ready()
|
|
23
|
-
t.same(core, core1)
|
|
24
|
-
}
|
|
19
|
+
t.alike(core1a.key, core1b.key)
|
|
20
|
+
t.unlike(core1a.key, core2.key)
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const core = store.get(core1.key.toString('hex'))
|
|
29
|
-
await toPromises(core).ready()
|
|
30
|
-
t.same(core, core1)
|
|
31
|
-
}
|
|
22
|
+
t.ok(core1a.writable)
|
|
23
|
+
t.ok(core1b.writable)
|
|
32
24
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const core = store.get({ key: core1.key })
|
|
36
|
-
await toPromises(core).ready()
|
|
37
|
-
t.same(core, core1)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
// Object arg with string key
|
|
42
|
-
const core = store.get({ key: core1.key.toString('hex') })
|
|
43
|
-
await toPromises(core).ready()
|
|
44
|
-
t.same(core, core1)
|
|
45
|
-
}
|
|
25
|
+
t.is(store.cores.size, 2)
|
|
26
|
+
})
|
|
46
27
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
t.same(core, core1)
|
|
52
|
-
}
|
|
28
|
+
test('basic get with custom keypair', async function (t) {
|
|
29
|
+
const store = new Corestore(ram)
|
|
30
|
+
const kp1 = crypto.keyPair()
|
|
31
|
+
const kp2 = crypto.keyPair()
|
|
53
32
|
|
|
54
|
-
|
|
55
|
-
|
|
33
|
+
const core1 = store.get(kp1)
|
|
34
|
+
const core2 = store.get(kp2)
|
|
35
|
+
await Promise.all([core1.ready(), core2.ready()])
|
|
56
36
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
() => store.get('abc'),
|
|
62
|
-
() => store.get({ name: null }),
|
|
63
|
-
() => store.get({ key: null })
|
|
64
|
-
]
|
|
65
|
-
for (const get of badGets) {
|
|
66
|
-
try {
|
|
67
|
-
get()
|
|
68
|
-
t.fail('get did not throw correctly')
|
|
69
|
-
} catch (err) {
|
|
70
|
-
t.true(err)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
37
|
+
t.alike(core1.key, kp1.publicKey)
|
|
38
|
+
t.alike(core2.key, kp2.publicKey)
|
|
39
|
+
t.ok(core1.writable)
|
|
40
|
+
t.ok(core2.writable)
|
|
73
41
|
})
|
|
74
42
|
|
|
75
|
-
test('
|
|
76
|
-
const store =
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
await Promise.all([
|
|
82
|
-
toPromises(core1).ready(),
|
|
83
|
-
toPromises(core2).ready(),
|
|
84
|
-
toPromises(core3).ready()
|
|
85
|
-
])
|
|
43
|
+
test('basic namespaces', async function (t) {
|
|
44
|
+
const store = new Corestore(ram)
|
|
45
|
+
const ns1 = store.namespace('ns1')
|
|
46
|
+
const ns2 = store.namespace('ns2')
|
|
47
|
+
const ns3 = store.namespace('ns1') // Duplicate namespace
|
|
86
48
|
|
|
87
|
-
|
|
88
|
-
|
|
49
|
+
const core1 = ns1.get({ name: 'main' })
|
|
50
|
+
const core2 = ns2.get({ name: 'main' })
|
|
51
|
+
const core3 = ns3.get({ name: 'main' })
|
|
52
|
+
await Promise.all([core1.ready(), core2.ready(), core3.ready()])
|
|
89
53
|
|
|
90
|
-
|
|
91
|
-
t.
|
|
54
|
+
t.absent(core1.key.equals(core2.key))
|
|
55
|
+
t.ok(core1.key.equals(core3.key))
|
|
56
|
+
t.ok(core1.writable)
|
|
57
|
+
t.ok(core2.writable)
|
|
58
|
+
t.ok(core3.writable)
|
|
59
|
+
t.is(store.cores.size, 2)
|
|
92
60
|
|
|
93
61
|
t.end()
|
|
94
62
|
})
|
|
95
63
|
|
|
96
|
-
test('
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
await core.ready()
|
|
64
|
+
test('basic replication', async function (t) {
|
|
65
|
+
const store1 = new Corestore(ram)
|
|
66
|
+
const store2 = new Corestore(ram)
|
|
100
67
|
|
|
101
|
-
const
|
|
102
|
-
|
|
68
|
+
const core1 = store1.get({ name: 'core-1' })
|
|
69
|
+
const core2 = store1.get({ name: 'core-2' })
|
|
70
|
+
await core1.append('hello')
|
|
71
|
+
await core2.append('world')
|
|
103
72
|
|
|
104
|
-
|
|
105
|
-
|
|
73
|
+
const core3 = store2.get({ key: core1.key })
|
|
74
|
+
const core4 = store2.get({ key: core2.key })
|
|
106
75
|
|
|
107
|
-
|
|
76
|
+
const s = store1.replicate(true)
|
|
77
|
+
s.pipe(store2.replicate(false)).pipe(s)
|
|
78
|
+
|
|
79
|
+
t.alike(await core3.get(0), Buffer.from('hello'))
|
|
80
|
+
t.alike(await core4.get(0), Buffer.from('world'))
|
|
108
81
|
})
|
|
109
82
|
|
|
110
|
-
test('
|
|
111
|
-
const store1 =
|
|
112
|
-
const store2 =
|
|
83
|
+
test('replicating cores created after replication begins', async function (t) {
|
|
84
|
+
const store1 = new Corestore(ram)
|
|
85
|
+
const store2 = new Corestore(ram)
|
|
113
86
|
|
|
114
|
-
const
|
|
87
|
+
const s = store1.replicate(true, { live: true })
|
|
88
|
+
s.pipe(store2.replicate(false, { live: true })).pipe(s)
|
|
89
|
+
|
|
90
|
+
const core1 = store1.get({ name: 'core-1' })
|
|
91
|
+
const core2 = store1.get({ name: 'core-2' })
|
|
115
92
|
await core1.append('hello')
|
|
93
|
+
await core2.append('world')
|
|
116
94
|
|
|
117
|
-
const
|
|
118
|
-
|
|
95
|
+
const core3 = store2.get({ key: core1.key })
|
|
96
|
+
const core4 = store2.get({ key: core2.key })
|
|
119
97
|
|
|
120
|
-
|
|
121
|
-
t.
|
|
98
|
+
t.alike(await core3.get(0), Buffer.from('hello'))
|
|
99
|
+
t.alike(await core4.get(0), Buffer.from('world'))
|
|
100
|
+
})
|
|
122
101
|
|
|
123
|
-
|
|
124
|
-
|
|
102
|
+
test('replicating cores using discovery key hook', async function (t) {
|
|
103
|
+
const dir = tmpdir()
|
|
104
|
+
let store1 = new Corestore(dir)
|
|
105
|
+
const store2 = new Corestore(ram)
|
|
125
106
|
|
|
126
|
-
const
|
|
127
|
-
|
|
107
|
+
const core = store1.get({ name: 'main' })
|
|
108
|
+
await core.append('hello')
|
|
109
|
+
const key = core.key
|
|
128
110
|
|
|
129
|
-
|
|
111
|
+
await store1.close()
|
|
112
|
+
store1 = new Corestore(dir)
|
|
113
|
+
|
|
114
|
+
const s = store1.replicate(true, { live: true })
|
|
115
|
+
s.pipe(store2.replicate(false, { live: true })).pipe(s)
|
|
116
|
+
|
|
117
|
+
const core2 = store2.get(key)
|
|
118
|
+
t.alike(await core2.get(0), Buffer.from('hello'))
|
|
130
119
|
})
|
|
131
120
|
|
|
132
|
-
test('
|
|
133
|
-
const
|
|
134
|
-
const
|
|
121
|
+
test('nested namespaces', async function (t) {
|
|
122
|
+
const store = new Corestore(ram)
|
|
123
|
+
const ns1a = store.namespace('ns1').namespace('a')
|
|
124
|
+
const ns1b = store.namespace('ns1').namespace('b')
|
|
135
125
|
|
|
136
|
-
const core1 =
|
|
137
|
-
|
|
126
|
+
const core1 = ns1a.get({ name: 'main' })
|
|
127
|
+
const core2 = ns1b.get({ name: 'main' })
|
|
128
|
+
await Promise.all([core1.ready(), core2.ready()])
|
|
138
129
|
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
t.not(core1.key.equals(core2.key))
|
|
131
|
+
t.ok(core1.writable)
|
|
132
|
+
t.ok(core2.writable)
|
|
133
|
+
t.is(store.cores.size, 2)
|
|
134
|
+
})
|
|
141
135
|
|
|
142
|
-
|
|
143
|
-
|
|
136
|
+
test('core uncached when all sessions close', async function (t) {
|
|
137
|
+
const store = new Corestore(ram)
|
|
138
|
+
const core1 = store.get({ name: 'main' })
|
|
139
|
+
await core1.ready()
|
|
140
|
+
t.is(store.cores.size, 1)
|
|
141
|
+
await core1.close()
|
|
142
|
+
t.is(store.cores.size, 0)
|
|
143
|
+
})
|
|
144
144
|
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
test('writable core loaded from name userData', async function (t) {
|
|
146
|
+
const dir = tmpdir()
|
|
147
147
|
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
let store = new Corestore(dir)
|
|
149
|
+
let core = store.get({ name: 'main' })
|
|
150
|
+
await core.ready()
|
|
151
|
+
const key = core.key
|
|
150
152
|
|
|
151
|
-
t.
|
|
153
|
+
t.ok(core.writable)
|
|
154
|
+
await core.append('hello')
|
|
155
|
+
t.is(core.length, 1)
|
|
156
|
+
|
|
157
|
+
await store.close()
|
|
158
|
+
store = new Corestore(dir)
|
|
159
|
+
core = store.get(key)
|
|
160
|
+
await core.ready()
|
|
161
|
+
|
|
162
|
+
t.ok(core.writable)
|
|
163
|
+
await core.append('world')
|
|
164
|
+
t.is(core.length, 2)
|
|
165
|
+
t.alike(await core.get(0), Buffer.from('hello'))
|
|
166
|
+
t.alike(await core.get(1), Buffer.from('world'))
|
|
152
167
|
})
|
|
153
168
|
|
|
154
|
-
test('
|
|
155
|
-
const
|
|
156
|
-
const store2 = create(path => raf(p.join('store2', path)))
|
|
169
|
+
test('writable core loaded from name and namespace userData', async function (t) {
|
|
170
|
+
const dir = tmpdir()
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
|
|
172
|
+
let store = new Corestore(dir)
|
|
173
|
+
let core = store.namespace('ns1').get({ name: 'main' })
|
|
174
|
+
await core.ready()
|
|
175
|
+
const key = core.key
|
|
160
176
|
|
|
161
|
-
|
|
162
|
-
|
|
177
|
+
t.ok(core.writable)
|
|
178
|
+
await core.append('hello')
|
|
179
|
+
t.is(core.length, 1)
|
|
163
180
|
|
|
164
|
-
|
|
165
|
-
|
|
181
|
+
await store.close()
|
|
182
|
+
store = new Corestore(dir)
|
|
183
|
+
core = store.get(key)
|
|
184
|
+
await core.ready()
|
|
166
185
|
|
|
167
|
-
|
|
168
|
-
await
|
|
186
|
+
t.ok(core.writable)
|
|
187
|
+
await core.append('world')
|
|
188
|
+
t.is(core.length, 2)
|
|
189
|
+
t.alike(await core.get(0), Buffer.from('hello'))
|
|
190
|
+
t.alike(await core.get(1), Buffer.from('world'))
|
|
191
|
+
})
|
|
169
192
|
|
|
170
|
-
|
|
171
|
-
|
|
193
|
+
test('storage locking', async function (t) {
|
|
194
|
+
const dir = tmpdir()
|
|
172
195
|
|
|
173
|
-
|
|
174
|
-
|
|
196
|
+
const store1 = new Corestore(dir)
|
|
197
|
+
await store1.ready()
|
|
198
|
+
|
|
199
|
+
const store2 = new Corestore(dir)
|
|
200
|
+
try {
|
|
201
|
+
await store2.ready()
|
|
202
|
+
t.fail('dir should have been locked')
|
|
203
|
+
} catch {
|
|
204
|
+
t.pass('dir was locked')
|
|
205
|
+
}
|
|
175
206
|
})
|
|
176
207
|
|
|
177
|
-
test('
|
|
178
|
-
|
|
208
|
+
test('closing a namespace does not close cores', async function (t) {
|
|
209
|
+
const store = new Corestore(ram)
|
|
210
|
+
const ns1 = store.namespace('ns1')
|
|
211
|
+
const core1 = ns1.get({ name: 'core-1' })
|
|
212
|
+
const core2 = ns1.get({ name: 'core-2' })
|
|
213
|
+
await Promise.all([core1.ready(), core2.ready()])
|
|
179
214
|
|
|
180
|
-
|
|
181
|
-
await core1.append('hello')
|
|
215
|
+
await ns1.close()
|
|
182
216
|
|
|
183
|
-
t.
|
|
217
|
+
t.is(store.cores.size, 2)
|
|
218
|
+
t.not(core1.closed)
|
|
219
|
+
t.not(core1.closed)
|
|
184
220
|
|
|
185
221
|
await store.close()
|
|
186
|
-
store = create('test-store')
|
|
187
|
-
core1 = toPromises(store.get({ name: 'core1', valueEncoding: 'utf-8' }))
|
|
188
|
-
|
|
189
|
-
t.same(await core1.get(0), 'hello')
|
|
190
222
|
|
|
191
|
-
|
|
192
|
-
t.
|
|
223
|
+
t.is(store.cores.size, 0)
|
|
224
|
+
t.ok(core1.closed)
|
|
225
|
+
t.ok(core2.closed)
|
|
193
226
|
})
|
|
194
227
|
|
|
195
|
-
test('
|
|
196
|
-
|
|
197
|
-
const keyPair = hypercoreCrypto.keyPair()
|
|
228
|
+
test('findingPeers', async function (t) {
|
|
229
|
+
t.plan(6)
|
|
198
230
|
|
|
199
|
-
|
|
200
|
-
await core1.append('hello')
|
|
231
|
+
const store = new Corestore(ram)
|
|
201
232
|
|
|
202
|
-
|
|
233
|
+
const ns1 = store.namespace('ns1')
|
|
234
|
+
const ns2 = store.namespace('ns2')
|
|
203
235
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
core1 = toPromises(store.get({ keyPair, valueEncoding: 'utf-8' }))
|
|
236
|
+
const a = ns1.get(Buffer.alloc(32).fill('a'))
|
|
237
|
+
const b = ns2.get(Buffer.alloc(32).fill('b'))
|
|
207
238
|
|
|
208
|
-
|
|
239
|
+
const done = ns1.findingPeers()
|
|
209
240
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
241
|
+
let aUpdated = false
|
|
242
|
+
let bUpdated = false
|
|
243
|
+
let cUpdated = false
|
|
213
244
|
|
|
214
|
-
|
|
215
|
-
const store = create(ram)
|
|
245
|
+
const c = ns1.get(Buffer.alloc(32).fill('c'))
|
|
216
246
|
|
|
217
|
-
|
|
218
|
-
|
|
247
|
+
a.update().then(function (bool) {
|
|
248
|
+
aUpdated = true
|
|
249
|
+
})
|
|
219
250
|
|
|
220
|
-
|
|
221
|
-
|
|
251
|
+
b.update().then(function (bool) {
|
|
252
|
+
bUpdated = true
|
|
253
|
+
})
|
|
222
254
|
|
|
223
|
-
|
|
224
|
-
|
|
255
|
+
c.update().then(function (bool) {
|
|
256
|
+
cUpdated = true
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
await new Promise(resolve => setImmediate(resolve))
|
|
260
|
+
|
|
261
|
+
t.is(aUpdated, false)
|
|
262
|
+
t.is(bUpdated, true)
|
|
263
|
+
t.is(cUpdated, false)
|
|
264
|
+
|
|
265
|
+
done()
|
|
266
|
+
|
|
267
|
+
await new Promise(resolve => setImmediate(resolve))
|
|
268
|
+
|
|
269
|
+
t.is(aUpdated, true)
|
|
270
|
+
t.is(bUpdated, true)
|
|
271
|
+
t.is(cUpdated, true)
|
|
225
272
|
})
|
|
226
273
|
|
|
227
|
-
test('
|
|
228
|
-
const
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
const manifest = await firstStore.backup()
|
|
274
|
+
test('different primary keys yield different keypairs', async function (t) {
|
|
275
|
+
const pk1 = randomBytes(32)
|
|
276
|
+
const pk2 = randomBytes(32)
|
|
277
|
+
t.unlike(pk1, pk2)
|
|
232
278
|
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
await toPromises(core2).ready()
|
|
279
|
+
const store1 = new Corestore(ram, { primaryKey: pk1 })
|
|
280
|
+
const store2 = new Corestore(ram, { primaryKey: pk2 })
|
|
236
281
|
|
|
237
|
-
|
|
282
|
+
const kp1 = await store1.createKeyPair('hello')
|
|
283
|
+
const kp2 = await store2.createKeyPair('hello')
|
|
238
284
|
|
|
239
|
-
t.
|
|
285
|
+
t.unlike(kp1.publicKey, kp2.publicKey)
|
|
240
286
|
})
|
|
241
287
|
|
|
242
|
-
test('
|
|
243
|
-
const
|
|
244
|
-
await
|
|
245
|
-
|
|
246
|
-
const oldCores = [
|
|
247
|
-
oldStore.default(),
|
|
248
|
-
oldStore.namespace('hello').default(),
|
|
249
|
-
oldStore.namespace('hello').namespace('world').default(),
|
|
250
|
-
oldStore.get({ name: 'test-name' }),
|
|
251
|
-
// Randomly-generated names should also be migrated.
|
|
252
|
-
oldStore.get()
|
|
253
|
-
]
|
|
254
|
-
await Promise.all(oldCores.map(c => new Promise(resolve => c.ready(resolve))))
|
|
255
|
-
|
|
256
|
-
const names = [
|
|
257
|
-
'default',
|
|
258
|
-
['hello'],
|
|
259
|
-
['hello', 'world'],
|
|
260
|
-
'test-name'
|
|
261
|
-
]
|
|
262
|
-
const keys = oldCores.map(c => c.key)
|
|
263
|
-
await new Promise(resolve => oldStore.close(resolve))
|
|
264
|
-
|
|
265
|
-
{
|
|
266
|
-
const store = create('test-store', {
|
|
267
|
-
migrationRoot: 'test-store'
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
// Cores are writable when loaded by name
|
|
271
|
-
for (let i = 0; i < names.length; i++) {
|
|
272
|
-
const core = store.get({ name: names[i] })
|
|
273
|
-
await toPromises(core).ready()
|
|
274
|
-
t.true(core.writable)
|
|
275
|
-
t.same(core.key, keys[i])
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
await store.close()
|
|
279
|
-
}
|
|
288
|
+
test('keypair auth sign', async function (t) {
|
|
289
|
+
const store = new Corestore(ram)
|
|
290
|
+
const keyPair = await store.createKeyPair('foo')
|
|
291
|
+
const message = b4a.from('hello world')
|
|
280
292
|
|
|
281
|
-
|
|
282
|
-
// The second time should work without a migration.
|
|
283
|
-
const store = create('test-store')
|
|
293
|
+
const sig = keyPair.auth.sign(message)
|
|
284
294
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
t.true(core.writable)
|
|
290
|
-
}
|
|
295
|
+
t.is(sig.length, 64)
|
|
296
|
+
t.ok(crypto.verify(message, sig, keyPair.publicKey))
|
|
297
|
+
t.absent(crypto.verify(message, b4a.alloc(64), keyPair.publicKey))
|
|
298
|
+
})
|
|
291
299
|
|
|
292
|
-
|
|
293
|
-
|
|
300
|
+
test('keypair auth verify', async function (t) {
|
|
301
|
+
const store = new Corestore(ram)
|
|
302
|
+
const keyPair = await store.createKeyPair('foo')
|
|
303
|
+
const message = b4a.from('hello world')
|
|
294
304
|
|
|
295
|
-
|
|
296
|
-
|
|
305
|
+
const sig = crypto.sign(message, keyPair.secretKey)
|
|
306
|
+
|
|
307
|
+
t.is(sig.length, 64)
|
|
308
|
+
t.ok(keyPair.auth.verify(message, sig))
|
|
309
|
+
t.absent(keyPair.auth.verify(message, b4a.alloc(64)))
|
|
297
310
|
})
|
|
298
311
|
|
|
299
|
-
|
|
300
|
-
const store = new Corestore(
|
|
301
|
-
|
|
312
|
+
test('core caching after reopen regression', async function (t) {
|
|
313
|
+
const store = new Corestore(ram)
|
|
314
|
+
const core = store.get({ name: 'test-core' })
|
|
315
|
+
await core.ready()
|
|
316
|
+
|
|
317
|
+
core.close()
|
|
318
|
+
await core.opening
|
|
319
|
+
|
|
320
|
+
const core2 = store.get({ name: 'test-core' })
|
|
321
|
+
await core2.ready()
|
|
322
|
+
|
|
323
|
+
t.pass('did not infinite loop')
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
function tmpdir () {
|
|
327
|
+
return path.join(os.tmpdir(), 'corestore-' + Math.random().toString(16).slice(2))
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function randomBytes (n) {
|
|
331
|
+
const buf = b4a.allocUnsafe(n)
|
|
332
|
+
sodium.randombytes_buf(buf)
|
|
333
|
+
return buf
|
|
302
334
|
}
|
package/test/cache.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const test = require('brittle')
|
|
2
|
+
const RAM = require('random-access-memory')
|
|
3
|
+
|
|
4
|
+
const Corestore = require('..')
|
|
5
|
+
|
|
6
|
+
test('core cache', async function (t) {
|
|
7
|
+
const store = new Corestore(RAM, { cache: true })
|
|
8
|
+
|
|
9
|
+
const core = store.get({ name: 'core' })
|
|
10
|
+
await core.append(['a', 'b', 'c'])
|
|
11
|
+
|
|
12
|
+
const p = core.get(0)
|
|
13
|
+
const q = core.get(0)
|
|
14
|
+
|
|
15
|
+
t.is(await p, await q)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
test('clear cache on truncate', async function (t) {
|
|
19
|
+
const store = new Corestore(RAM, { cache: true })
|
|
20
|
+
|
|
21
|
+
const core = store.get({ name: 'core' })
|
|
22
|
+
await core.append(['a', 'b', 'c'])
|
|
23
|
+
|
|
24
|
+
const p = core.get(0)
|
|
25
|
+
|
|
26
|
+
await core.truncate(0)
|
|
27
|
+
await core.append('d')
|
|
28
|
+
|
|
29
|
+
const q = core.get(0)
|
|
30
|
+
|
|
31
|
+
t.alike(await p, Buffer.from('a'))
|
|
32
|
+
t.alike(await q, Buffer.from('d'))
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test('core cache on namespace', async function (t) {
|
|
36
|
+
const store = new Corestore(RAM, { cache: true })
|
|
37
|
+
const ns1 = store.namespace('test-namespace-1')
|
|
38
|
+
|
|
39
|
+
const c1 = store.get({ name: 'test-core' })
|
|
40
|
+
const c2 = ns1.get({ name: 'test-core' })
|
|
41
|
+
|
|
42
|
+
await Promise.all([c1.ready(), c2.ready()])
|
|
43
|
+
|
|
44
|
+
t.ok(c1.cache)
|
|
45
|
+
t.ok(c2.cache)
|
|
46
|
+
})
|
package/test/helpers/index.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
1
|
+
const fs = require('fs').promises
|
|
2
2
|
|
|
3
3
|
async function cleanup (dirs) {
|
|
4
|
-
return Promise.
|
|
5
|
-
fs.rmdir(dir, { recursive: true }, err => {
|
|
6
|
-
if (err) return reject(err)
|
|
7
|
-
return resolve()
|
|
8
|
-
})
|
|
9
|
-
})))
|
|
4
|
+
return Promise.allSettled(dirs.map(dir => fs.rmdir(dir, { recursive: true })))
|
|
10
5
|
}
|
|
11
6
|
|
|
12
7
|
function delay (ms, cb) {
|
package/lib/buffer-file.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const RAS = require('random-access-storage')
|
|
2
|
-
|
|
3
|
-
module.exports = class BufferFile extends RAS {
|
|
4
|
-
constructor (buf) {
|
|
5
|
-
super()
|
|
6
|
-
this._buf = buf
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
_open (req) {
|
|
10
|
-
if (typeof this._buf !== 'function') return req.callback(null)
|
|
11
|
-
this._buf((err, b) => {
|
|
12
|
-
if (err) return req.callback(err)
|
|
13
|
-
this._buf = b
|
|
14
|
-
req.callback(null)
|
|
15
|
-
})
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
_stat (req) {
|
|
19
|
-
req.callback(null, { size: this._buf ? this._buf.length : 0 })
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
_read (req) {
|
|
23
|
-
if (!this._buf) return req.callback(new Error('Could not satisfy length'))
|
|
24
|
-
req.callback(null, this._buf.slice(req.offset, req.offset + req.size))
|
|
25
|
-
}
|
|
26
|
-
}
|