Skip to content
This repository was archived by the owner on Oct 1, 2021. It is now read-only.

Commit 6f4acf7

Browse files
authored
test: adds tests for multi-bucket pin migration (#29)
Once the number of pinned blocks is over 8192, a second layer of pins is created in the pinset data structure. This PR refactors the tests to use car files of CIDs/blocks to recreate this pinset structure and ensure we can migrate backwards and forwards between them. It also adds tests for directly pinned and also non-dag-pb blocks to ensure those pins are migrated sucessfully.
1 parent 749f042 commit 6f4acf7

12 files changed

+311
-115
lines changed

.aegir.js

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
'use strict'
22

33
module.exports = {
4+
karma: {
5+
// multi-bucket pinset migrations are slow
6+
browserNoActivityTimeout: 240 * 1000
7+
},
48
webpack: {
59
node: {
610
// this is needed until level stops using node buffers in browser code

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ node_modules
2828
package-lock.json
2929
yarn.lock
3030
# Tests
31-
test/test-repo-for*
31+
test-repo-for*
3232
test/sharness/tmp

.travis.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ jobs:
5454
name: electron-main
5555
os: osx
5656
script:
57-
- npx aegir test -t electron-main --bail --timeout 10000
57+
- npx aegir test -t electron-main --bail --timeout 10000 -f test/node.js
5858

5959
- stage: test
6060
name: electron-renderer
6161
os: osx
6262
script:
63-
- npx aegir test -t electron-renderer --bail --timeout 10000
63+
- npx aegir test -t electron-renderer --bail --timeout 10000 -f test/node.js
6464

6565
notifications:
6666
email: false

migrations/migration-9/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ async function pinsToDatastore (blockstore, datastore, pinstore) {
2121
}
2222

2323
if (cid.version !== 0) {
24-
pin.version = version
24+
pin.version = cid.version
2525
}
2626

2727
if (cid.codec !== 'dag-pb') {
@@ -37,7 +37,7 @@ async function pinsToDatastore (blockstore, datastore, pinstore) {
3737
}
3838

3939
if (cid.version !== 0) {
40-
pin.version = version
40+
pin.version = cid.version
4141
}
4242

4343
if (cid.codec !== 'dag-pb') {

migrations/migration-9/pin-set.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ function readHeader (rootNode) {
5454
}
5555

5656
function hash (seed, key) {
57-
const buffer = new ArrayBuffer(4)
58-
const dataView = new DataView(buffer)
57+
const buffer = new Uint8Array(4)
58+
const dataView = new DataView(buffer.buffer)
5959
dataView.setUint32(0, seed, true)
6060
const encodedKey = uint8ArrayFromString(toB58String(key))
61-
const data = uint8ArrayConcat([buf, encodedKey], buf.length + encodedKey.length)
61+
const data = uint8ArrayConcat([buffer, encodedKey], buffer.byteLength + encodedKey.byteLength)
6262

6363
return fnv1a(uint8ArrayToString(data))
6464
}
@@ -168,7 +168,7 @@ function storeItems (blockstore, items) {
168168

169169
async function storeChild (child, binIdx) {
170170
const buf = dagpb.util.serialize(child)
171-
const cid = dagpb.util.cid(buf, {
171+
const cid = await dagpb.util.cid(buf, {
172172
cidVersion: 0,
173173
hashAlg: multicodec.SHA2_256,
174174
})

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"aegir": "^25.0.0",
6969
"chai": "^4.2.0",
7070
"chai-as-promised": "^7.1.1",
71+
"datastore-car": "^1.2.0",
7172
"dirty-chai": "^2.0.1",
7273
"it-all": "^1.0.2",
7374
"just-safe-set": "^2.1.0",

test/fixtures/generate-car-files.js

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
'use strict'
2+
3+
/* eslint-disable no-console */
4+
5+
// nb. must be [email protected] or below
6+
const IPFS = require('ipfs')
7+
const {
8+
CID
9+
} = IPFS
10+
const { Key } = require('interface-datastore')
11+
const PIN_DS_KEY = new Key('/local/pins')
12+
const fs = require('fs')
13+
const CarDatastore = require('datastore-car')
14+
const path = require('path')
15+
16+
const TO_PIN = 9000
17+
18+
const main = async () => {
19+
const ipfs = await IPFS.create({
20+
profile: 'lowpower'
21+
})
22+
23+
const directPins = []
24+
25+
for (let i = TO_PIN; i < TO_PIN + 10; i++) {
26+
const data = `hello-${i}`
27+
const { cid } = await ipfs.add(data, { pin: false })
28+
29+
await ipfs.pin.add(cid, {
30+
recursive: false
31+
})
32+
33+
directPins.push(cid)
34+
}
35+
36+
console.info('const directPins = [')
37+
console.info(' ', directPins.map(cid => `'${cid}'`).join(',\n '))
38+
console.info(']')
39+
40+
const nonDagPbRecursivePins = []
41+
42+
for (let i = TO_PIN + 10; i < TO_PIN + 20; i++) {
43+
const data = { derp: `hello-${i}` }
44+
const cid = await ipfs.dag.put(data)
45+
46+
await ipfs.pin.add(cid, {
47+
recursive: true
48+
})
49+
50+
nonDagPbRecursivePins.push(`${cid}`)
51+
}
52+
53+
console.info('const nonDagPbRecursivePins = [')
54+
console.info(' ', nonDagPbRecursivePins.join(',\n '))
55+
console.info(']')
56+
57+
const nonDagPbDirectPins = []
58+
59+
for (let i = TO_PIN + 20; i < TO_PIN + 30; i++) {
60+
const data = { derp: `hello-${i}` }
61+
const cid = await ipfs.dag.put(data)
62+
63+
await ipfs.pin.add(cid, {
64+
recursive: false
65+
})
66+
67+
nonDagPbDirectPins.push(`${cid}`)
68+
}
69+
70+
console.info('const nonDagPbDirectPins = [')
71+
console.info(' ', nonDagPbDirectPins.join(',\n '))
72+
console.info(']')
73+
74+
console.info('const pinsets = {')
75+
76+
await writeCar('basic pinset', true)
77+
78+
for (let i = 0; i < TO_PIN; i++) {
79+
const data = `hello-${i}`
80+
await ipfs.add(data)
81+
}
82+
83+
await writeCar('multiple buckets pinset')
84+
85+
console.info('}')
86+
87+
await ipfs.stop()
88+
89+
async function writeCar (pinsetName, more) {
90+
const fileName = `pinset-${pinsetName.replace(/\s/g, '-').replace('-pinset', '')}.car`
91+
92+
console.info(` '${pinsetName}': {`)
93+
console.info(` car: loadFixture('test/fixtures/${fileName}'),`)
94+
95+
const buf = await ipfs.libp2p.datastore.get(PIN_DS_KEY)
96+
const cid = new CID(buf)
97+
98+
console.info(` root: new CID('${cid}'),`)
99+
100+
const outStream = fs.createWriteStream(path.join(__dirname, fileName))
101+
const car = await CarDatastore.writeStream(outStream)
102+
103+
await car.setRoots(cid)
104+
105+
await walk(cid, car)
106+
107+
let pins = 0
108+
109+
for await (const _ of ipfs.pin.ls()) { // eslint-disable-line no-unused-vars
110+
pins++
111+
}
112+
113+
console.info(` pins: ${pins}`)
114+
console.info(` }${more ? ',' : ''}`)
115+
116+
await car.close()
117+
}
118+
119+
async function walk (cid, car, cids = {}) {
120+
if (cids[cid.toString()]) {
121+
return
122+
}
123+
124+
cids[cid.toString()] = true
125+
126+
const block = await ipfs.block.get(cid)
127+
128+
car.put(cid, block.data)
129+
130+
const { value: node } = await ipfs.dag.get(cid)
131+
132+
if (node.Links) {
133+
for (const link of node.Links) {
134+
await walk(link.Hash, car, cids)
135+
}
136+
}
137+
}
138+
}
139+
140+
main()
141+
.catch(err => {
142+
console.error(err)
143+
process.exit(1)
144+
})

test/fixtures/pinset-basic.car

32 KB
Binary file not shown.
3.48 MB
Binary file not shown.

test/migrations/index.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
/* eslint-env mocha */
22
'use strict'
33

4+
const DatastoreLevel = require('datastore-level')
5+
46
const CONFIGURATIONS = [{
57
name: 'with sharding',
68
options: {
9+
storageBackends: {
10+
pins: DatastoreLevel
11+
},
712
storageBackendOptions: {
813
root: {
914
sharding: true,
@@ -21,7 +26,7 @@ const CONFIGURATIONS = [{
2126
sharding: true,
2227
extension: '.data'
2328
},
24-
pinstore: {
29+
pins: {
2530
sharding: true,
2631
extension: '.data'
2732
}
@@ -30,6 +35,9 @@ const CONFIGURATIONS = [{
3035
}, {
3136
name: 'without sharding',
3237
options: {
38+
storageBackends: {
39+
pins: DatastoreLevel
40+
},
3341
storageBackendOptions: {
3442
root: {
3543
sharding: false,
@@ -47,7 +55,7 @@ const CONFIGURATIONS = [{
4755
sharding: false,
4856
extension: '.data'
4957
},
50-
pinstore: {
58+
pins: {
5159
sharding: false,
5260
extension: '.data'
5361
}

test/migrations/migration-8-test.js

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
/* eslint-env mocha */
22
'use strict'
33

4-
const chai = require('chai')
5-
chai.use(require('dirty-chai'))
6-
const chaiAsPromised = require('chai-as-promised')
7-
chai.use(chaiAsPromised)
8-
const expect = chai.expect
4+
const { expect } = require('aegir/utils/chai')
95

106
const migration = require('../../migrations/migration-8')
117
const Key = require('interface-datastore').Key

0 commit comments

Comments
 (0)