hypercore 10.0.0-alpha.8 → 10.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.
package/test/replicate.js DELETED
@@ -1,372 +0,0 @@
1
- const test = require('brittle')
2
- const NoiseSecretStream = require('@hyperswarm/secret-stream')
3
- const { create, replicate, eventFlush } = require('./helpers')
4
-
5
- test('basic replication', async function (t) {
6
- const a = await create()
7
-
8
- await a.append(['a', 'b', 'c', 'd', 'e'])
9
-
10
- const b = await create(a.key)
11
-
12
- let d = 0
13
- b.on('download', () => d++)
14
-
15
- replicate(a, b, t)
16
-
17
- const r = b.download({ start: 0, end: a.length })
18
-
19
- await r.downloaded()
20
-
21
- t.is(d, 5)
22
- })
23
-
24
- test('basic replication from fork', async function (t) {
25
- const a = await create()
26
-
27
- await a.append(['a', 'b', 'c', 'd', 'e'])
28
- await a.truncate(4)
29
- await a.append('e')
30
-
31
- t.is(a.fork, 1)
32
-
33
- const b = await create(a.key)
34
-
35
- replicate(a, b, t)
36
-
37
- let d = 0
38
- b.on('download', () => d++)
39
-
40
- const r = b.download({ start: 0, end: a.length })
41
-
42
- await r.downloaded()
43
-
44
- t.is(d, 5)
45
- t.is(a.fork, b.fork)
46
- })
47
-
48
- test('eager replication from bigger fork', async function (t) {
49
- const a = await create()
50
- const b = await create(a.key)
51
-
52
- replicate(a, b, t)
53
-
54
- await a.append(['a', 'b', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k'])
55
- await a.truncate(4)
56
- await a.append(['FORKED', 'g', 'h', 'i', 'j', 'k'])
57
-
58
- t.is(a.fork, 1)
59
-
60
- let d = 0
61
- b.on('download', (index) => {
62
- d++
63
- })
64
-
65
- const r = b.download({ start: 0, end: a.length })
66
-
67
- await r.downloaded()
68
-
69
- t.is(d, a.length)
70
- t.is(a.fork, b.fork)
71
- })
72
-
73
- test('eager replication of updates per default', async function (t) {
74
- const a = await create()
75
- const b = await create(a.key)
76
-
77
- replicate(a, b, t)
78
-
79
- const appended = new Promise(resolve => {
80
- b.on('append', function () {
81
- t.pass('appended')
82
- resolve()
83
- })
84
- })
85
-
86
- await a.append(['a', 'b', 'c', 'd', 'e', 'g', 'h', 'i', 'j', 'k'])
87
- await appended
88
- })
89
-
90
- test('bigger download range', async function (t) {
91
- const a = await create()
92
- const b = await create(a.key)
93
-
94
- replicate(a, b, t)
95
-
96
- for (let i = 0; i < 20; i++) await a.append('data')
97
-
98
- const downloaded = new Set()
99
-
100
- b.on('download', function (index) {
101
- downloaded.add(index)
102
- })
103
-
104
- const r = b.download({ start: 0, end: a.length })
105
- await r.downloaded()
106
-
107
- t.is(b.length, a.length, 'same length')
108
- t.is(downloaded.size, a.length, 'downloaded all')
109
-
110
- t.end()
111
- })
112
-
113
- test('high latency reorg', async function (t) {
114
- const a = await create()
115
- const b = await create(a.key)
116
-
117
- const s = replicate(a, b, t)
118
-
119
- for (let i = 0; i < 50; i++) await a.append('data')
120
-
121
- {
122
- const r = b.download({ start: 0, end: a.length })
123
- await r.downloaded()
124
- }
125
-
126
- s[0].destroy()
127
- s[1].destroy()
128
-
129
- await a.truncate(30)
130
-
131
- for (let i = 0; i < 50; i++) await a.append('fork')
132
-
133
- replicate(a, b, t)
134
-
135
- {
136
- const r = b.download({ start: 0, end: a.length })
137
- await r.downloaded()
138
- }
139
-
140
- let same = 0
141
-
142
- for (let i = 0; i < a.length; i++) {
143
- const ba = await a.get(i)
144
- const bb = await b.get(i)
145
- if (ba.equals(bb)) same++
146
- }
147
-
148
- t.is(a.fork, 1)
149
- t.is(a.fork, b.fork)
150
- t.is(same, 80)
151
- })
152
-
153
- test('invalid signature fails', async function (t) {
154
- t.plan(2)
155
-
156
- const a = await create()
157
- const b = await create() // not the same key
158
-
159
- b.discoveryKey = a.discoveryKey // haxx to make them swarm
160
-
161
- await a.append(['a', 'b', 'c', 'd', 'e'])
162
-
163
- const [s1, s2] = replicate(a, b, t)
164
-
165
- s1.on('error', (err) => {
166
- t.ok(err, 'stream closed')
167
- })
168
-
169
- s2.on('error', (err) => {
170
- t.is(err.message, 'Remote signature does not match')
171
- })
172
-
173
- return new Promise((resolve) => {
174
- let missing = 2
175
-
176
- s1.on('close', onclose)
177
- s2.on('close', onclose)
178
-
179
- function onclose () {
180
- if (--missing === 0) resolve()
181
- }
182
- })
183
- })
184
-
185
- test('update with zero length', async function (t) {
186
- const a = await create()
187
- const b = await create(a.key)
188
-
189
- replicate(a, b, t)
190
-
191
- await b.update() // should not hang
192
- t.is(b.length, 0)
193
- })
194
-
195
- test('basic multiplexing', async function (t) {
196
- const a1 = await create()
197
- const a2 = await create()
198
-
199
- const b1 = await create(a1.key)
200
- const b2 = await create(a2.key)
201
-
202
- const a = a1.replicate(a2.replicate(true))
203
- const b = b1.replicate(b2.replicate(false))
204
-
205
- a.pipe(b).pipe(a)
206
-
207
- await a1.append('hi')
208
- t.alike(await b1.get(0), Buffer.from('hi'))
209
-
210
- await a2.append('ho')
211
- t.alike(await b2.get(0), Buffer.from('ho'))
212
- })
213
-
214
- test('async multiplexing', async function (t) {
215
- const a1 = await create()
216
- const b1 = await create(a1.key)
217
-
218
- const a = a1.replicate(true)
219
- const b = b1.replicate(false)
220
-
221
- a.pipe(b).pipe(a)
222
-
223
- const a2 = await create()
224
- await a2.append('ho')
225
-
226
- const b2 = await create(a2.key)
227
-
228
- // b2 doesn't replicate immediately.
229
- a2.replicate(a)
230
- await eventFlush()
231
- b2.replicate(b)
232
-
233
- await new Promise(resolve => b2.once('peer-add', resolve))
234
-
235
- t.is(b2.peers.length, 1)
236
- t.alike(await b2.get(0), Buffer.from('ho'))
237
- })
238
-
239
- test('multiplexing with external noise stream', async function (t) {
240
- const a1 = await create()
241
- const a2 = await create()
242
-
243
- const b1 = await create(a1.key)
244
- const b2 = await create(a2.key)
245
-
246
- const n1 = new NoiseSecretStream(true)
247
- const n2 = new NoiseSecretStream(false)
248
- n1.rawStream.pipe(n2.rawStream).pipe(n1.rawStream)
249
-
250
- a1.replicate(n1)
251
- a2.replicate(n1)
252
- b1.replicate(n2)
253
- b2.replicate(n2)
254
-
255
- await a1.append('hi')
256
- t.alike(await b1.get(0), Buffer.from('hi'))
257
-
258
- await a2.append('ho')
259
- t.alike(await b2.get(0), Buffer.from('ho'))
260
- })
261
-
262
- test('seeking while replicating', async function (t) {
263
- const a = await create()
264
- const b = await create(a.key)
265
-
266
- replicate(a, b, t)
267
-
268
- await a.append(['hello', 'this', 'is', 'test', 'data'])
269
-
270
- t.alike(await b.seek(6), [1, 1])
271
- })
272
-
273
- test('multiplexing multiple times over the same stream', async function (t) {
274
- const a1 = await create()
275
-
276
- await a1.append('hi')
277
-
278
- const b1 = await create(a1.key)
279
-
280
- const n1 = new NoiseSecretStream(true)
281
- const n2 = new NoiseSecretStream(false)
282
-
283
- n1.rawStream.pipe(n2.rawStream).pipe(n1.rawStream)
284
-
285
- a1.replicate(n1)
286
-
287
- b1.replicate(n2)
288
- b1.replicate(n2)
289
-
290
- t.ok(await b1.update(), 'update once')
291
- t.absent(await a1.update(), 'writer up to date')
292
- t.absent(await b1.update(), 'update again')
293
-
294
- t.is(b1.length, a1.length, 'same length')
295
- t.end()
296
- })
297
-
298
- test('destroying a stream and re-replicating works', async function (t) {
299
- const core = await create()
300
-
301
- while (core.length < 33) await core.append(Buffer.from('#' + core.length))
302
-
303
- const clone = await create(core.key)
304
-
305
- let s1 = core.replicate(true)
306
- let s2 = clone.replicate(false)
307
-
308
- s1.pipe(s2).pipe(s1)
309
-
310
- await s2.opened
311
-
312
- const all = []
313
- for (let i = 0; i < 33; i++) {
314
- all.push(clone.get(i))
315
- }
316
-
317
- clone.once('download', function () {
318
- // simulate stream failure in the middle of bulk downloading
319
- s1.destroy()
320
- })
321
-
322
- await new Promise((resolve) => s1.once('close', resolve))
323
-
324
- // retry
325
- s1 = core.replicate(true)
326
- s2 = clone.replicate(false)
327
-
328
- s1.pipe(s2).pipe(s1)
329
-
330
- const blocks = await Promise.all(all)
331
-
332
- t.is(blocks.length, 33, 'downloaded 33 blocks')
333
- })
334
-
335
- test('replicate discrete range', async function (t) {
336
- const a = await create()
337
-
338
- await a.append(['a', 'b', 'c', 'd', 'e'])
339
-
340
- const b = await create(a.key)
341
-
342
- let d = 0
343
- b.on('download', () => d++)
344
-
345
- replicate(a, b, t)
346
-
347
- const r = b.download({ blocks: [0, 2, 3] })
348
- await r.downloaded()
349
-
350
- t.is(d, 3)
351
- t.alike(await b.get(0), Buffer.from('a'))
352
- t.alike(await b.get(2), Buffer.from('c'))
353
- t.alike(await b.get(3), Buffer.from('d'))
354
- })
355
-
356
- test('replicate discrete empty range', async function (t) {
357
- const a = await create()
358
-
359
- await a.append(['a', 'b', 'c', 'd', 'e'])
360
-
361
- const b = await create(a.key)
362
-
363
- let d = 0
364
- b.on('download', () => d++)
365
-
366
- replicate(a, b, t)
367
-
368
- const r = b.download({ blocks: [] })
369
- await r.downloaded()
370
-
371
- t.is(d, 0)
372
- })
package/test/sessions.js DELETED
@@ -1,173 +0,0 @@
1
- const test = require('brittle')
2
- const ram = require('random-access-memory')
3
- const crypto = require('hypercore-crypto')
4
-
5
- const Hypercore = require('../')
6
-
7
- test('sessions - can create writable sessions from a read-only core', async function (t) {
8
- t.plan(5)
9
-
10
- const keyPair = crypto.keyPair()
11
- const core = new Hypercore(ram, keyPair.publicKey, {
12
- valueEncoding: 'utf-8'
13
- })
14
- await core.ready()
15
- t.absent(core.writable)
16
-
17
- const session = core.session({ keyPair: { secretKey: keyPair.secretKey } })
18
- t.ok(session.writable)
19
-
20
- try {
21
- await core.append('hello')
22
- t.fail('should not have appended to the read-only core')
23
- } catch {
24
- t.pass('read-only core append threw correctly')
25
- }
26
-
27
- try {
28
- await session.append('world')
29
- t.pass('session append did not throw')
30
- } catch {
31
- t.fail('session append should not have thrown')
32
- }
33
-
34
- t.is(core.length, 1)
35
- t.end()
36
- })
37
-
38
- test('sessions - writable session with custom sign function', async function (t) {
39
- t.plan(5)
40
-
41
- const keyPair = crypto.keyPair()
42
- const core = new Hypercore(ram, keyPair.publicKey, {
43
- valueEncoding: 'utf-8'
44
- })
45
- await core.ready()
46
- t.absent(core.writable)
47
-
48
- const session = core.session({ sign: signable => crypto.sign(signable, keyPair.secretKey) })
49
- t.ok(session.writable)
50
-
51
- try {
52
- await core.append('hello')
53
- t.fail('should not have appended to the read-only core')
54
- } catch {
55
- t.pass('read-only core append threw correctly')
56
- }
57
-
58
- try {
59
- await session.append('world')
60
- t.pass('session append did not throw')
61
- } catch {
62
- t.fail('session append should not have thrown')
63
- }
64
-
65
- t.is(core.length, 1)
66
- t.end()
67
- })
68
-
69
- test('sessions - writable session with invalid keypair throws', async function (t) {
70
- t.plan(2)
71
-
72
- const keyPair1 = crypto.keyPair()
73
- const keyPair2 = crypto.keyPair()
74
-
75
- try {
76
- const core = new Hypercore(ram, keyPair2.publicKey) // Create a new core in read-only mode.
77
- core.session({ keyPair: keyPair1 })
78
- t.fail('invalid keypair did not throw')
79
- } catch {
80
- t.pass('invalid keypair threw')
81
- }
82
-
83
- try {
84
- const core = new Hypercore(ram, keyPair1.publicKey, { keyPair: keyPair2 }) // eslint-disable-line
85
- await core.ready()
86
- t.fail('invalid keypair did not throw')
87
- } catch {
88
- t.pass('invalid keypair threw')
89
- }
90
- })
91
-
92
- test('sessions - auto close', async function (t) {
93
- const core = new Hypercore(ram, { autoClose: true })
94
-
95
- let closed = false
96
- core.on('close', function () {
97
- closed = true
98
- })
99
-
100
- const a = core.session()
101
- const b = core.session()
102
-
103
- await a.close()
104
- t.absent(closed, 'not closed yet')
105
-
106
- await b.close()
107
- t.ok(closed, 'all closed')
108
- })
109
-
110
- test('sessions - auto close different order', async function (t) {
111
- const core = new Hypercore(ram, { autoClose: true })
112
-
113
- const a = core.session()
114
- const b = core.session()
115
-
116
- let closed = false
117
- a.on('close', function () {
118
- closed = true
119
- })
120
-
121
- await core.close()
122
- t.absent(closed, 'not closed yet')
123
-
124
- await b.close()
125
- t.ok(closed, 'all closed')
126
- })
127
-
128
- test('sessions - auto close with all closing', async function (t) {
129
- const core = new Hypercore(ram, { autoClose: true })
130
-
131
- const a = core.session()
132
- const b = core.session()
133
-
134
- let closed = 0
135
- a.on('close', () => closed++)
136
- b.on('close', () => closed++)
137
- core.on('close', () => closed++)
138
-
139
- await Promise.all([core.close(), a.close(), b.close()])
140
- t.is(closed, 3, 'all closed')
141
- })
142
-
143
- test('sessions - auto close when using from option', async function (t) {
144
- const core1 = new Hypercore(ram, {
145
- autoClose: true
146
- })
147
- const core2 = new Hypercore({
148
- preload: () => {
149
- return {
150
- from: core1
151
- }
152
- }
153
- })
154
- await core2.close()
155
- t.ok(core1.closed)
156
- })
157
-
158
- test('sessions - close with from option', async function (t) {
159
- const core1 = new Hypercore(ram)
160
- await core1.append('hello world')
161
-
162
- const core2 = new Hypercore({
163
- preload: () => {
164
- return {
165
- from: core1
166
- }
167
- }
168
- })
169
- await core2.close()
170
-
171
- t.absent(core1.closed)
172
- t.alike(await core1.get(0), Buffer.from('hello world'))
173
- })
package/test/user-data.js DELETED
@@ -1,47 +0,0 @@
1
- const test = require('brittle')
2
- const Hypercore = require('../')
3
- const tmp = require('tmp-promise')
4
- const { create } = require('./helpers')
5
-
6
- test('userdata - can set through setUserData', async function (t) {
7
- const core = await create()
8
- await core.setUserData('hello', Buffer.from('world'))
9
-
10
- t.alike(await core.getUserData('hello'), Buffer.from('world'))
11
-
12
- t.end()
13
- })
14
-
15
- test('userdata - can set through constructor option', async function (t) {
16
- const core = await create({
17
- userData: {
18
- hello: Buffer.from('world')
19
- }
20
- })
21
-
22
- t.alike(await core.getUserData('hello'), Buffer.from('world'))
23
-
24
- t.end()
25
- })
26
-
27
- test('userdata - persists across restarts', async function (t) {
28
- const dir = await tmp.dir()
29
-
30
- let core = new Hypercore(dir.path, {
31
- userData: {
32
- hello: Buffer.from('world')
33
- }
34
- })
35
- await core.ready()
36
-
37
- await core.close()
38
- core = new Hypercore(dir.path, {
39
- userData: {
40
- other: Buffer.from('another')
41
- }
42
- })
43
-
44
- t.alike(await core.getUserData('hello'), Buffer.from('world'))
45
- t.alike(await core.getUserData('other'), Buffer.from('another'))
46
- t.end()
47
- })