Skip to content

fix: add cross-impl shard test, fix path cleaner #358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 75 additions & 28 deletions packages/ipfs-unixfs-exporter/test/exporter-sharded.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,40 +256,87 @@ describe('exporter sharded', function () {
expect(exported.name).to.deep.equal('file-1')
})

it('exports a shard with a different fanout size', async () => {
const files: ImportCandidate[] = [{
path: '/baz.txt',
content: Uint8Array.from([0, 1, 2, 3, 4])
}, {
path: '/foo.txt',
content: Uint8Array.from([0, 1, 2, 3, 4])
}, {
path: '/bar.txt',
content: Uint8Array.from([0, 1, 2, 3, 4])
}]
describe('alternate fanout size', function () {
it('exports a shard with a fanout of 16', async () => {
const files: ImportCandidate[] = [{
path: '/baz.txt',
content: Uint8Array.from([0, 1, 2, 3, 4])
}, {
path: '/foo.txt',
content: Uint8Array.from([0, 1, 2, 3, 4])
}, {
path: '/bar.txt',
content: Uint8Array.from([0, 1, 2, 3, 4])
}]

const result = await last(importer(files, block, {
shardSplitThresholdBytes: 0,
shardFanoutBits: 4, // 2**4 = 16 children max
wrapWithDirectory: true
}))
const result = await last(importer(files, block, {
shardSplitThresholdBytes: 0,
shardFanoutBits: 4, // 2**4 = 16 children max
wrapWithDirectory: true
}))

if (result == null) {
throw new Error('Import failed')
}
if (result == null) {
throw new Error('Import failed')
}

const { cid } = result
const dir = await exporter(cid, block)
const { cid } = result
const dir = await exporter(cid, block)

expect(dir).to.have.nested.property('unixfs.fanout', 16n)

const contents = await all(dir.content())

expect(dir).to.have.nested.property('unixfs.fanout', 16n)
expect(contents.map(entry => ({
path: `/${entry.name}`,
content: entry.node
})))
.to.deep.equal(files)
})

// Cross-impl reference test: directory of files with single character
// names, starting from ' ' and ending with '~', but excluding the special
// characters '/' and '.'. Each file should contain a single byte with the
// same value as the character in its name. Files are added to a sharded
// directory with a fanout of 16, using CIDv1 throughout, and should result
// in the root CID of:
// bafybeihnipspiyy3dctpcx7lv655qpiuy52d7b2fzs52dtrjqwmvbiux44
it('reference shard with fanout of 16', async () => {
const files: ImportCandidate[] = []
for (let ch = ' '.charCodeAt(0); ch <= '~'.charCodeAt(0); ch++) {
if (ch === 47 || ch === 46) { // skip '/' and '.'
continue
}
files.push({
path: String.fromCharCode(ch),
content: Uint8Array.from([ch])
})
}

const contents = await all(dir.content())
const result = await last(importer(files, block, {
shardSplitThresholdBytes: 0,
shardFanoutBits: 4,
wrapWithDirectory: true
}))

expect(contents.map(entry => ({
path: `/${entry.name}`,
content: entry.node
})))
.to.deep.equal(files)
if (result == null) {
throw new Error('Import failed')
}

const { cid } = result
expect(cid.toString()).to.equal('bafybeihnipspiyy3dctpcx7lv655qpiuy52d7b2fzs52dtrjqwmvbiux44')

const dir = await exporter(cid, block)

expect(dir).to.have.nested.property('unixfs.fanout', 16n)

let contents = await all(dir.content())
contents = contents.map(entry => ({
path: `${entry.name}`,
content: entry.node
}))
contents.sort((a, b) => a.content[0] < b.content[0] ? -1 : 1)
expect(contents).to.deep.equal(files)
})
})

it('walks path of a HAMT with a different fanout size', async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
export const toPathComponents = (path: string = ''): string[] => {
// split on / unless escaped with \
return (path
.trim()
.match(/([^\\/]|\\\/)+/g) ?? [])
.filter(Boolean)
return path.split(/(?<!\\)\//).filter(Boolean)
Copy link
Member Author

@rvagg rvagg Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's also a little odd to escape \ here because we don't do that elsewhere in ipfs-land, paths officially have no escaping mechanism but 🤷

}