From cebc65416cdfef202eb45238ac35d982c9b9f2d3 Mon Sep 17 00:00:00 2001 From: George Svarovsky Date: Sat, 19 Feb 2022 14:50:34 +0000 Subject: [PATCH] m-ld/m-ld-js#93: Additional test for snapshot integrity m-ld/m-ld-security-spec#3: Unauthorised error --- compliance/1-start/2-start-colony.spec.js | 54 +++++++++++++--------- compliance/1-start/3-active-colony.spec.js | 2 +- compliance/clone.js | 4 +- types/index.ts | 10 +++- 4 files changed, 45 insertions(+), 25 deletions(-) diff --git a/compliance/1-start/2-start-colony.spec.js b/compliance/1-start/2-start-colony.spec.js index 7cbdafb..0f9edca 100644 --- a/compliance/1-start/2-start-colony.spec.js +++ b/compliance/1-start/2-start-colony.spec.js @@ -4,36 +4,48 @@ const Clone = require('../clone'); * Basic multi-clone startup tests (no transactions) */ describe('Colony', () => { - let clone1, clone2; - - beforeEach(() => { - clone1 = new Clone(); - clone2 = new Clone(); - }); + let clones; it('clones start', async () => { - await clone1.start(); - await expectAsync(clone2.start()).toBeResolved(); + clones = [new Clone, new Clone]; + await clones[0].start(); + await expectAsync(clones[1].start()).toBeResolved(); }); it('clone can restart', async () => { - await clone1.start(true); - await clone2.start(); - await clone1.stop(); - await expectAsync(clone1.start()).toBeResolved(); + clones = [new Clone, new Clone]; + await clones[0].start(true); + await clones[1].start(); + await clones[0].stop(); + await expectAsync(clones[0].start()).toBeResolved(); }); it('clone can restart alone', async () => { - await clone1.start(true); - await clone2.start(); - await clone1.stop(); - await clone2.stop(); - await expectAsync(clone1.start()).toBeResolved(); + clones = [new Clone, new Clone]; + await clones[0].start(true); + await clones[1].start(); + await clones[0].stop(); + await clones[1].stop(); + await expectAsync(clones[0].start()).toBeResolved(); + }); + + it('start from non-genesis', async () => { + clones = [new Clone, new Clone, new Clone]; + await clones[0].start(true); + await clones[0].transact({ '@id': 'fred', name: 'Fred' }); + await clones[1].start(); // Receive snapshot from clones[0] + await clones[0].transact({ '@id': 'wilma', name: 'Wilma' }); + await clones[1].updated('@insert', 'wilma'); + /* + This captures an edge-case former bug in the JS engine. At this point + clones[1] may drop the pre-fork journal entry 'fred', but when responding to + clones[2]'s snapshot request, it was trying to fuse 'wilma' with it. + */ + await clones[1].transact({ '@id': 'barney', name: 'Barney' }); + await clones[0].stop(); + await expectAsync(clones[2].start()).toBeResolved(); }); - afterEach(async () => await Promise.all([ - clone1.destroy(), - clone2.destroy() - ])); + afterEach(() => Promise.all(clones.map(clone => clone.destroy()))); }); diff --git a/compliance/1-start/3-active-colony.spec.js b/compliance/1-start/3-active-colony.spec.js index ef9cf91..d5e52eb 100644 --- a/compliance/1-start/3-active-colony.spec.js +++ b/compliance/1-start/3-active-colony.spec.js @@ -48,6 +48,6 @@ describe('Active colony', () => { } }); - afterEach(async () => await Promise.all(clones.map(clone => clone.destroy()))); + afterEach(() => Promise.all(clones.map(clone => clone.destroy()))); }); diff --git a/compliance/clone.js b/compliance/clone.js index 83f7b3c..3cdd8f8 100644 --- a/compliance/clone.js +++ b/compliance/clone.js @@ -37,10 +37,10 @@ module.exports = class Clone extends EventEmitter { * Creates the requested number of clones, with the given configuration. The * returned clones are not started. * @param {number} count number of clones - * @param {MeldConfig} config configuration for all clones + * @param {MeldConfig} [config] configuration for all clones */ static create(count, config) { - return Array(count).fill().map(() => new Clone(config)); + return Array(count).fill(undefined).map(() => new Clone(config)); } /** diff --git a/types/index.ts b/types/index.ts index 0ea2009..0dd6dfa 100644 --- a/types/index.ts +++ b/types/index.ts @@ -163,7 +163,15 @@ export enum MeldErrorStatus { 'Delta too big' = 4002, ////////////////////////////////////////////////////////////////////////////// - // Not found errors + // Unauthorised error + /** + * A request was made for data for which the current security principal does + * not have access rights. + */ + 'Unauthorised' = 4030, + + ////////////////////////////////////////////////////////////////////////////// + // Not found error /** * A request was made for updates in the too-distant past. This can occur when * following clone updates, or when re-starting a clone that has been offline