1 | const tape = require('tape')
|
2 | const hypercoreCrypto = require('hypercore-crypto')
|
3 | const Corestore = require('corestore')
|
4 | const ram = require('random-access-memory')
|
5 | const create = require('./helpers/create')
|
6 | const Replicator = require('./helpers/replicator')
|
7 |
|
8 | tape('close event', function (t) {
|
9 | t.plan(1)
|
10 |
|
11 | var drive = create()
|
12 |
|
13 | drive.on('close', function () {
|
14 | t.pass('close event')
|
15 | t.end()
|
16 | })
|
17 |
|
18 | drive.ready(function () {
|
19 | drive.close()
|
20 | })
|
21 | })
|
22 |
|
23 | tape('write and read', function (t) {
|
24 | var drive = create()
|
25 |
|
26 | drive.writeFile('/hello.txt', 'world', function (err) {
|
27 | t.error(err, 'no error')
|
28 | drive.readFile('/hello.txt', function (err, buf) {
|
29 | t.error(err, 'no error')
|
30 | t.same(buf, Buffer.from('world'))
|
31 | t.end()
|
32 | })
|
33 | })
|
34 | })
|
35 |
|
36 | tape('write and read, with encoding', function (t) {
|
37 | var drive = create()
|
38 |
|
39 | drive.writeFile('/hello.txt', 'world', { encoding: 'utf8' }, function (err) {
|
40 | t.error(err, 'no error')
|
41 | drive.readFile('/hello.txt', { encoding: 'utf8' }, function (err, str) {
|
42 | t.error(err, 'no error')
|
43 | t.same(str, 'world')
|
44 | t.end()
|
45 | })
|
46 | })
|
47 | })
|
48 |
|
49 | tape('write and read (2 parallel)', function (t) {
|
50 | t.plan(6)
|
51 |
|
52 | var drive = create()
|
53 |
|
54 | drive.writeFile('/hello.txt', 'world', function (err) {
|
55 | t.error(err, 'no error')
|
56 | drive.readFile('/hello.txt', function (err, buf) {
|
57 | t.error(err, 'no error')
|
58 | t.same(buf, Buffer.from('world'))
|
59 | })
|
60 | })
|
61 |
|
62 | drive.writeFile('/world.txt', 'hello', function (err) {
|
63 | t.error(err, 'no error')
|
64 | drive.readFile('/world.txt', function (err, buf) {
|
65 | t.error(err, 'no error')
|
66 | t.same(buf, Buffer.from('hello'))
|
67 | })
|
68 | })
|
69 | })
|
70 |
|
71 | tape('write and read (sparse)', function (t) {
|
72 | var drive = create()
|
73 | drive.on('ready', function () {
|
74 | var clone = create(drive.key)
|
75 | var r = new Replicator(t)
|
76 |
|
77 | r.replicate(clone, drive)
|
78 |
|
79 | drive.writeFile('/hello.txt', 'world', function (err) {
|
80 | t.error(err, 'no error')
|
81 | var readStream = clone.createReadStream('/hello.txt')
|
82 | readStream.on('data', function (data) {
|
83 | t.same(data.toString(), 'world')
|
84 | r.end()
|
85 | })
|
86 | })
|
87 | })
|
88 | })
|
89 |
|
90 | tape('root is always there', function (t) {
|
91 | var drive = create()
|
92 |
|
93 | drive.access('/', function (err) {
|
94 | t.error(err, 'no error')
|
95 | drive.readdir('/', function (err, list) {
|
96 | t.error(err, 'no error')
|
97 | t.same(list, [])
|
98 | t.end()
|
99 | })
|
100 | })
|
101 | })
|
102 |
|
103 | tape('provide keypair', function (t) {
|
104 | const keyPair = hypercoreCrypto.keyPair()
|
105 | var drive = create(keyPair.publicKey, { keyPair })
|
106 |
|
107 | drive.on('ready', function () {
|
108 | t.ok(drive.writable)
|
109 | t.ok(drive.metadata.writable)
|
110 | t.ok(keyPair.publicKey.equals(drive.key))
|
111 |
|
112 | drive.writeFile('/hello.txt', 'world', function (err) {
|
113 | t.error(err, 'no error')
|
114 | drive.readFile('/hello.txt', function (err, buf) {
|
115 | t.error(err, 'no error')
|
116 | t.same(buf, Buffer.from('world'))
|
117 | t.end()
|
118 | })
|
119 | })
|
120 | })
|
121 | })
|
122 |
|
123 | tape.skip('can reopen when providing a keypair', function (t) {
|
124 | const keyPair = hypercoreCrypto.keyPair()
|
125 | const store = new Corestore(ram)
|
126 | var drive = create(keyPair.publicKey, { keyPair, corestore: store })
|
127 |
|
128 | drive.on('ready', function () {
|
129 | t.ok(drive.writable)
|
130 | t.ok(drive.metadata.writable)
|
131 | t.ok(keyPair.publicKey.equals(drive.key))
|
132 |
|
133 | drive.writeFile('/hello.txt', 'world', function (err) {
|
134 | t.error(err, 'no error')
|
135 | console.log('CORE LENGTH BEFORE CLOSE:', drive.metadata.length)
|
136 | drive.close(err => {
|
137 | t.error(err, 'no error')
|
138 | drive = create(keyPair.publicKey, { keyPair, corestore: store })
|
139 |
|
140 | drive.on('ready', function () {
|
141 | console.log('CORE LENGTH:', drive.metadata.length)
|
142 | t.ok(drive.writable)
|
143 | t.ok(drive.metadata.writable)
|
144 | t.ok(keyPair.publicKey.equals(drive.key))
|
145 |
|
146 | drive.readFile('/hello.txt', function (err, buf) {
|
147 | t.error(err, 'no error')
|
148 | t.same(buf, Buffer.from('world'))
|
149 | t.end()
|
150 | })
|
151 | })
|
152 | })
|
153 | })
|
154 | })
|
155 | })
|
156 |
|
157 | tape('write and read, no cache', function (t) {
|
158 | var drive = create({
|
159 | metadataStorageCacheSize: 0,
|
160 | contentStorageCacheSize: 0,
|
161 | treeCacheSize: 0
|
162 | })
|
163 |
|
164 | drive.writeFile('/hello.txt', 'world', function (err) {
|
165 | t.error(err, 'no error')
|
166 | drive.readFile('/hello.txt', function (err, buf) {
|
167 | t.error(err, 'no error')
|
168 | t.same(buf, Buffer.from('world'))
|
169 | t.end()
|
170 | })
|
171 | })
|
172 | })
|
173 |
|
174 | tape('can read a single directory', async function (t) {
|
175 | const drive = create(null)
|
176 |
|
177 | let files = ['a', 'b', 'c', 'd', 'e', 'f']
|
178 | let fileSet = new Set(files)
|
179 |
|
180 | for (let file of files) {
|
181 | await insertFile(file, 'a small file')
|
182 | }
|
183 |
|
184 | drive.readdir('/', (err, files) => {
|
185 | t.error(err, 'no error')
|
186 | for (let file of files) {
|
187 | t.true(fileSet.has(file), 'correct file was listed')
|
188 | fileSet.delete(file)
|
189 | }
|
190 | t.same(fileSet.size, 0, 'all files were listed')
|
191 | t.end()
|
192 | })
|
193 |
|
194 | function insertFile (name, content) {
|
195 | return new Promise((resolve, reject) => {
|
196 | drive.writeFile(name, content, err => {
|
197 | if (err) return reject(err)
|
198 | return resolve()
|
199 | })
|
200 | })
|
201 | }
|
202 | })
|
203 |
|
204 | tape.skip('can stream a large directory', async function (t) {
|
205 | const drive = create(null)
|
206 |
|
207 | let files = new Array(1000).fill(0).map((_, idx) => '' + idx)
|
208 | let fileSet = new Set(files)
|
209 |
|
210 | for (let file of files) {
|
211 | await insertFile(file, 'a small file')
|
212 | }
|
213 |
|
214 | let stream = drive.createDirectoryStream('/')
|
215 | stream.on('data', ({ path, stat }) => {
|
216 | if (!fileSet.has(path)) {
|
217 | return t.fail('an incorrect file was streamed')
|
218 | }
|
219 | fileSet.delete(path)
|
220 | })
|
221 | stream.on('end', () => {
|
222 | t.same(fileSet.size, 0, 'all files were streamed')
|
223 | t.end()
|
224 | })
|
225 |
|
226 | function insertFile (name, content) {
|
227 | return new Promise((resolve, reject) => {
|
228 | drive.writeFile(name, content, err => {
|
229 | if (err) return reject(err)
|
230 | return resolve()
|
231 | })
|
232 | })
|
233 | }
|
234 | })
|
235 |
|
236 | tape('can read sparse metadata', async function (t) {
|
237 | const r = new Replicator(t)
|
238 | const { read, write } = await getTestDrives()
|
239 |
|
240 | let files = ['a', 'b/a/b', 'b/c', 'c/b', 'd/e/f/g/h', 'd/e/a', 'e/a', 'e/b', 'f', 'g']
|
241 |
|
242 | for (let file of files) {
|
243 | await insertFile(file, 'a small file')
|
244 | await checkFile(file)
|
245 | }
|
246 |
|
247 | r.end()
|
248 |
|
249 | function checkFile (file) {
|
250 | return new Promise(resolve => {
|
251 | read.stat(file, (err, st) => {
|
252 | t.error(err, 'no error')
|
253 | t.true(st)
|
254 | return resolve()
|
255 | })
|
256 | })
|
257 | }
|
258 |
|
259 | function insertFile (name, content) {
|
260 | return new Promise((resolve, reject) => {
|
261 | write.writeFile(name, content, err => {
|
262 | if (err) return reject(err)
|
263 | return resolve()
|
264 | })
|
265 | })
|
266 | }
|
267 |
|
268 | function getTestDrives () {
|
269 | return new Promise(resolve => {
|
270 | let drive = create()
|
271 | drive.on('ready', () => {
|
272 | let clone = create(drive.key, { sparseMetadata: true, sparse: true })
|
273 | r.replicate(clone, drive)
|
274 | return resolve({ read: clone, write: drive })
|
275 | })
|
276 | })
|
277 | }
|
278 | })
|
279 |
|
280 | tape('unavailable drive becomes ready', function (t) {
|
281 | var drive1 = create()
|
282 | var drive2 = null
|
283 |
|
284 | drive1.ready(err => {
|
285 | t.error(err, 'no error')
|
286 | drive2 = create(drive1.key)
|
287 | drive2.ready(err => {
|
288 | t.error(err, 'no error')
|
289 | drive2.readFile('blah', (err, contents) => {
|
290 | t.true(err)
|
291 | t.same(err.errno, 2)
|
292 | t.end()
|
293 | })
|
294 | })
|
295 | })
|
296 | })
|
297 |
|
298 | tape('copy', function (t) {
|
299 | var drive = create()
|
300 | drive.ready(err => {
|
301 | t.error(err, 'no error')
|
302 | drive.writeFile('hello', 'world', err => {
|
303 | t.error(err, 'no error')
|
304 | drive.copy('hello', 'also_hello', err => {
|
305 | t.error(err, 'no error')
|
306 | drive.readFile('hello', { encoding: 'utf8' }, (err, contents) => {
|
307 | t.error(err, 'no error')
|
308 | t.same(contents, 'world')
|
309 | drive.readFile('also_hello', { encoding: 'utf8' }, (err, contents) => {
|
310 | t.error(err, 'no error')
|
311 | t.same(contents, 'world')
|
312 | t.end()
|
313 | })
|
314 | })
|
315 | })
|
316 | })
|
317 | })
|
318 | })
|