This repository has been archived by the owner on Jul 3, 2019. It is now read-only.
/
put.js
156 lines (144 loc) · 4.62 KB
/
put.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
'use strict'
const BB = require('bluebird')
const fromString = require('./util/from-string')
const fs = BB.promisifyAll(require('fs'))
const index = require('../lib/entry-index')
const memo = require('../lib/memoization')
const path = require('path')
const pipe = BB.promisify(require('mississippi').pipe)
const test = require('tap').test
const testDir = require('./util/test-dir')(__filename)
const ssri = require('ssri')
const CACHE = path.join(testDir, 'cache')
const CONTENT = Buffer.from('foobarbaz', 'utf8')
const KEY = 'my-test-key'
const INTEGRITY = ssri.fromData(CONTENT).toString()
const METADATA = { foo: 'bar' }
const contentPath = require('../lib/content/path')
var put = require('..').put
test('basic bulk insertion', t => {
return put(CACHE, KEY, CONTENT).then(integrity => {
t.equal(integrity.toString(), INTEGRITY, 'returned content integrity')
const dataPath = contentPath(CACHE, integrity)
return fs.readFileAsync(dataPath)
}).then(data => {
t.deepEqual(data, CONTENT, 'content was correctly inserted')
})
})
test('basic stream insertion', t => {
let int
const src = fromString(CONTENT)
const stream = put.stream(CACHE, KEY).on('integrity', i => {
int = i
})
return pipe(src, stream).then(() => {
t.equal(int.toString(), INTEGRITY, 'returned integrity matches expected')
return fs.readFileAsync(contentPath(CACHE, int))
}).then(data => {
t.deepEqual(data, CONTENT, 'contents are identical to inserted content')
})
})
test('adds correct entry to index before finishing', t => {
return put(CACHE, KEY, CONTENT, { metadata: METADATA }).then(() => {
return index.find(CACHE, KEY)
}).then(entry => {
t.ok(entry, 'got an entry')
t.equal(entry.key, KEY, 'entry has the right key')
t.equal(entry.integrity, INTEGRITY, 'entry has the right key')
t.deepEqual(entry.metadata, METADATA, 'metadata also inserted')
})
})
test('optionally memoizes data on bulk insertion', t => {
return put(CACHE, KEY, CONTENT, {
metadata: METADATA,
memoize: true
}).then(integrity => {
t.equal(integrity.toString(), INTEGRITY, 'integrity returned as usual')
return index.find(CACHE, KEY) // index.find is not memoized
}).then(entry => {
t.deepEqual(memo.get(CACHE, KEY), {
data: CONTENT,
entry: entry
}, 'content inserted into memoization cache by key')
t.deepEqual(
memo.get.byDigest(CACHE, INTEGRITY),
CONTENT,
'content inserted into memoization cache by integrity'
)
})
})
test('optionally memoizes data on stream insertion', t => {
let int
const src = fromString(CONTENT)
const stream = put.stream(CACHE, KEY, {
metadata: METADATA,
memoize: true
}).on('integrity', i => { int = i })
return pipe(src, stream).then(() => {
t.equal(int.toString(), INTEGRITY, 'integrity emitted as usual')
return fs.readFileAsync(contentPath(CACHE, int))
}).then(data => {
t.deepEqual(data, CONTENT, 'contents are identical to inserted content')
return index.find(CACHE, KEY) // index.find is not memoized
}).then(entry => {
t.deepEqual(memo.get(CACHE, KEY), {
data: CONTENT,
entry: entry
}, 'content inserted into memoization cache by key')
t.deepEqual(
memo.get.byDigest(CACHE, INTEGRITY),
CONTENT,
'content inserted into memoization cache by integrity'
)
})
})
test('errors if integrity errors', t => {
return BB.join(
put(CACHE, KEY, CONTENT, {
integrity: 'sha1-BaDDigEST'
}).catch(err => {
t.equal(err.code, 'EINTEGRITY', 'got error from bad integrity')
})
)
})
test('signals error if error writing to cache', t => {
return BB.join(
put(CACHE, KEY, CONTENT, {
size: 2
}).then(() => {
throw new Error('expected error')
}).catch(err => err),
pipe(fromString(CONTENT), put.stream(CACHE, KEY, {
size: 2
})).then(() => {
throw new Error('expected error')
}).catch(err => err),
(bulkErr, streamErr) => {
t.equal(bulkErr.code, 'EBADSIZE', 'got error from bulk write')
t.equal(streamErr.code, 'EBADSIZE', 'got error from stream write')
}
)
})
test('errors if input stream errors', t => {
let int
const putter = put.stream(CACHE, KEY).on('integrity', i => {
int = i
})
const stream = fromString(false)
return pipe(
stream, putter
).then(() => {
throw new Error('expected error')
}).catch(err => {
t.ok(err, 'got an error')
t.ok(!int, 'no integrity returned')
t.match(
err.message,
/Invalid non-string/,
'returns the error from input stream'
)
return fs.readdirAsync(testDir)
}).then(files => {
t.deepEqual(files, [], 'no files created')
})
})