@@ -7,6 +7,7 @@ const index = require('../lib/entry-index')
7
7
const fs = require ( 'graceful-fs' )
8
8
const path = require ( 'path' )
9
9
const Tacks = require ( 'tacks' )
10
+ const requireInject = require ( 'require-inject' )
10
11
const { test } = require ( 'tap' )
11
12
const testDir = require ( './util/test-dir' ) ( __filename )
12
13
const ssri = require ( 'ssri' )
@@ -29,6 +30,13 @@ const stat = util.promisify(fs.stat)
29
30
const appendFile = util . promisify ( fs . appendFile )
30
31
const writeFile = util . promisify ( fs . writeFile )
31
32
33
+ // defines reusable errors
34
+ const genericError = new Error ( 'ERR' )
35
+ genericError . code = 'ERR'
36
+
37
+ // helpers
38
+ const getVerify = ( opts ) => requireInject ( '../lib/verify' , opts )
39
+
32
40
function mockCache ( ) {
33
41
const fixture = new Tacks (
34
42
CacheContent ( {
@@ -264,6 +272,93 @@ test('writes a file with last verification time', (t) => {
264
272
265
273
test ( 'fixes permissions and users on cache contents' )
266
274
275
+ test ( 'missing file error when validating cache content' , ( t ) => {
276
+ const missingFileError = new Error ( 'ENOENT' )
277
+ missingFileError . code = 'ENOENT'
278
+ const mockVerify = getVerify ( {
279
+ 'graceful-fs' : Object . assign ( { } , fs , {
280
+ stat : ( path , cb ) => {
281
+ cb ( missingFileError )
282
+ }
283
+ } )
284
+ } )
285
+
286
+ t . plan ( 1 )
287
+ mockCache ( ) . then ( ( ) => {
288
+ t . resolveMatch (
289
+ mockVerify ( CACHE ) ,
290
+ {
291
+ verifiedContent : 0 ,
292
+ rejectedEntries : 1 ,
293
+ totalEntries : 0
294
+ } ,
295
+ 'should reject entry'
296
+ )
297
+ } )
298
+ } )
299
+
300
+ test ( 'unknown error when validating content' , ( t ) => {
301
+ const mockVerify = getVerify ( {
302
+ 'graceful-fs' : Object . assign ( { } , fs , {
303
+ stat : ( path , cb ) => {
304
+ cb ( genericError )
305
+ }
306
+ } )
307
+ } )
308
+
309
+ t . plan ( 1 )
310
+ mockCache ( ) . then ( ( ) => {
311
+ t . rejects (
312
+ mockVerify ( CACHE ) ,
313
+ genericError ,
314
+ 'should throw any unknown errors'
315
+ )
316
+ } )
317
+ } )
318
+
319
+ test ( 'unknown error when checking sri stream' , ( t ) => {
320
+ const mockVerify = getVerify ( {
321
+ ssri : Object . assign ( { } , ssri , {
322
+ checkStream : ( ) => Promise . reject ( genericError )
323
+ } )
324
+ } )
325
+
326
+ t . plan ( 1 )
327
+ mockCache ( ) . then ( ( ) => {
328
+ t . rejects (
329
+ mockVerify ( CACHE ) ,
330
+ genericError ,
331
+ 'should throw any unknown errors'
332
+ )
333
+ } )
334
+ } )
335
+
336
+ test ( 'unknown error when rebuilding bucket' , ( t ) => {
337
+ // rebuild bucket uses stat after content-validation
338
+ // shouldFail controls the right time to mock the error
339
+ let shouldFail = false
340
+ const mockVerify = getVerify ( {
341
+ 'graceful-fs' : Object . assign ( { } , fs , {
342
+ stat : ( path , cb ) => {
343
+ if ( shouldFail ) {
344
+ return cb ( genericError )
345
+ }
346
+ fs . stat ( path , cb )
347
+ shouldFail = true
348
+ }
349
+ } )
350
+ } )
351
+
352
+ t . plan ( 1 )
353
+ mockCache ( ) . then ( ( ) => {
354
+ t . rejects (
355
+ mockVerify ( CACHE ) ,
356
+ genericError ,
357
+ 'should throw any unknown errors'
358
+ )
359
+ } )
360
+ } )
361
+
267
362
test ( 're-builds the index with the size parameter' , ( t ) => {
268
363
const KEY2 = KEY + 'aaa'
269
364
const KEY3 = KEY + 'bbb'
@@ -312,3 +407,65 @@ test('re-builds the index with the size parameter', (t) => {
312
407
} )
313
408
} )
314
409
} )
410
+
411
+ test ( 'hash collisions' , ( t ) => {
412
+ const mockVerify = getVerify ( {
413
+ '../lib/entry-index' : Object . assign ( { } , index , {
414
+ hashKey : ( ) => 'aaa'
415
+ } )
416
+ } )
417
+
418
+ t . plan ( 1 )
419
+ mockCache ( )
420
+ . then ( ( ) =>
421
+ index . insert ( CACHE , 'foo' , INTEGRITY , {
422
+ metadata : 'foo'
423
+ } ) )
424
+ . then ( ( ) => mockVerify ( CACHE ) )
425
+ . then ( ( stats ) => {
426
+ t . deepEqual (
427
+ {
428
+ verifiedContent : stats . verifiedContent ,
429
+ rejectedEntries : stats . rejectedEntries ,
430
+ totalEntries : stats . totalEntries
431
+ } ,
432
+ {
433
+ verifiedContent : 1 ,
434
+ rejectedEntries : 0 ,
435
+ totalEntries : 2
436
+ } ,
437
+ 'should resolve with no errors'
438
+ )
439
+ } )
440
+ } )
441
+
442
+ test ( 'hash collisions excluded' , ( t ) => {
443
+ const mockVerify = getVerify ( {
444
+ '../lib/entry-index' : Object . assign ( { } , index , {
445
+ hashKey : ( ) => 'aaa'
446
+ } )
447
+ } )
448
+
449
+ t . plan ( 1 )
450
+ mockCache ( )
451
+ . then ( ( ) =>
452
+ index . insert ( CACHE , 'foo' , INTEGRITY , {
453
+ metadata : 'foo'
454
+ } ) )
455
+ . then ( ( ) => mockVerify ( CACHE , { filter : ( ) => null } ) )
456
+ . then ( ( stats ) => {
457
+ t . deepEqual (
458
+ {
459
+ verifiedContent : stats . verifiedContent ,
460
+ rejectedEntries : stats . rejectedEntries ,
461
+ totalEntries : stats . totalEntries
462
+ } ,
463
+ {
464
+ verifiedContent : 0 ,
465
+ rejectedEntries : 2 ,
466
+ totalEntries : 0
467
+ } ,
468
+ 'should resolve while also excluding filtered out entries'
469
+ )
470
+ } )
471
+ } )
0 commit comments