All files / src/crud-to-cas/__tests__ testCasfs.ts

100% Statements 87/87
100% Branches 0/0
100% Functions 17/17
100% Lines 85/85

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 1231x 1x 1x       1x 36x 36x 36x     1x 39x 39x                 1x 3x 3x 3x 3x 3x 3x 3x       3x 3x 3x 3x 3x 3x 3x     3x 3x 3x 3x 3x 3x 3x     3x 3x 3x 3x 3x 3x 3x 3x 3x     3x 3x 3x 3x 3x 3x 3x 3x       3x 3x 3x 3x 3x 3x 3x     3x 3x 3x 3x 3x 3x 3x       3x 3x 3x 3x 3x 3x 3x 3x 3x 3x     3x 3x 3x 3x 3x 3x 3x     3x 3x 3x 3x 3x        
import { of } from '../../thingies';
import { createHash } from 'crypto';
import { hashToLocation } from '../util';
import type { CasApi } from '../../cas/types';
import type { CrudApi } from '../../crud/types';
 
export const hash = async (blob: Uint8Array): Promise<string> => {
  const shasum = createHash('sha1');
  shasum.update(blob);
  return shasum.digest('hex');
};
 
const b = (str: string) => {
  const buf = Buffer.from(str);
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
};
 
export type Setup = () => {
  cas: CasApi<string>;
  crud: CrudApi;
  snapshot: () => Record<string, string | null>;
};
 
export const testCasfs = (setup: Setup) => {
  describe('.put()', () => {
    test('can store a blob', async () => {
      const blob = b('hello world');
      const { cas, snapshot } = setup();
      const hash = await cas.put(blob);
      expect(hash).toBe('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed');
      expect(snapshot()).toMatchSnapshot();
    });
  });
 
  describe('.get()', () => {
    test('can retrieve existing blob', async () => {
      const blob = b('hello world');
      const { cas } = setup();
      const hash = await cas.put(blob);
      const blob2 = await cas.get(hash);
      expect(blob2).toStrictEqual(blob);
    });
 
    test('throws if blob does not exist', async () => {
      const blob = b('hello world 2');
      const { cas } = setup();
      const hash = await cas.put(blob);
      const [, err] = await of(cas.get('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'));
      expect(err).toBeInstanceOf(DOMException);
      expect((<any>err).name).toBe('BlobNotFound');
    });
 
    test('throws if blob contents does not match the hash', async () => {
      const blob = b('hello world');
      const { cas, crud } = setup();
      const hash = await cas.put(blob);
      const location = hashToLocation(hash);
      await crud.put(location[0], location[1], b('hello world!'));
      const [, err] = await of(cas.get(hash));
      expect(err).toBeInstanceOf(DOMException);
      expect((<any>err).name).toBe('Integrity');
    });
 
    test('does not throw if integrity check is skipped', async () => {
      const blob = b('hello world');
      const { cas, crud } = setup();
      const hash = await cas.put(blob);
      const location = hashToLocation(hash);
      await crud.put(location[0], location[1], b('hello world!'));
      const blob2 = await cas.get(hash, { skipVerification: true });
      expect(blob2).toStrictEqual(b('hello world!'));
    });
  });
 
  describe('.info()', () => {
    test('can retrieve existing blob info', async () => {
      const blob = b('hello world');
      const { cas } = setup();
      const hash = await cas.put(blob);
      const info = await cas.info(hash);
      expect(info.size).toBe(11);
    });
 
    test('throws if blob does not exist', async () => {
      const blob = b('hello world 2');
      const { cas } = setup();
      const hash = await cas.put(blob);
      const [, err] = await of(cas.info('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'));
      expect(err).toBeInstanceOf(DOMException);
      expect((<any>err).name).toBe('BlobNotFound');
    });
  });
 
  describe('.del()', () => {
    test('can delete an existing blob', async () => {
      const blob = b('hello world');
      const { cas } = setup();
      const hash = await cas.put(blob);
      const info = await cas.info(hash);
      await cas.del(hash);
      const [, err] = await of(cas.info(hash));
      expect(err).toBeInstanceOf(DOMException);
      expect((<any>err).name).toBe('BlobNotFound');
    });
 
    test('throws if blob does not exist', async () => {
      const blob = b('hello world 2');
      const { cas } = setup();
      const hash = await cas.put(blob);
      const [, err] = await of(cas.del('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'));
      expect(err).toBeInstanceOf(DOMException);
      expect((<any>err).name).toBe('BlobNotFound');
    });
 
    test('does not throw if "silent" flag is provided', async () => {
      const blob = b('hello world 2');
      const { cas } = setup();
      const hash = await cas.put(blob);
      await cas.del('2aae6c35c94fcfb415dbe95f408b9ce91ee846ed', true);
    });
  });
};