From 1dab299e5ed329c65f6055d2b5917b4702a0c3c8 Mon Sep 17 00:00:00 2001 From: Ana <48334075+AnaDjokovic@users.noreply.github.com> Date: Tue, 14 Nov 2023 12:20:27 +0100 Subject: [PATCH] v6: Unit tests for validation module manager (#2663) * adding new unit tests * adding unit tests for validation manager module * update package.json script * remove unused methods * implement code review feedback and handle null in the validation functions * update test description * fix eslint errors * update operator from OR to AND --------- Co-authored-by: djordjekovac --- package.json | 2 +- .../validation/validation-module-manager.js | 21 ++- .../{ => unit}/modules/repository/config.json | 0 .../modules/repository/repository.test.js} | 8 +- .../modules/triple-store/config.json | 0 .../triple-store/triple-store.test.js} | 0 test/unit/modules/validation/config.json | 14 ++ .../validation-module-manager.test.js | 176 ++++++++++++++++++ 8 files changed, 215 insertions(+), 6 deletions(-) rename test/{ => unit}/modules/repository/config.json (100%) rename test/{modules/repository/repository.js => unit/modules/repository/repository.test.js} (98%) rename test/{ => unit}/modules/triple-store/config.json (100%) rename test/{modules/triple-store/triple-store.js => unit/modules/triple-store/triple-store.test.js} (100%) create mode 100644 test/unit/modules/validation/config.json create mode 100644 test/unit/modules/validation/validation-module-manager.test.js diff --git a/package.json b/package.json index 2b0fcf6fa2..00e8d27012 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "kill:local_blockchain": "npx kill-port 8545", "test:bdd": "cucumber-js --fail-fast --format progress --format-options '{\"colorsEnabled\": true}' test/bdd/ --import test/bdd/steps/ --exit", "test:unit": "nyc --all mocha --exit $(find test/unit -name '*.js')", - "test:modules": "nyc --all mocha --exit $(find test/modules -name '*.js')", + "test:modules": "nyc --all mocha --exit $(find test/unit/modules -name '*.js')", "test:bdd:release": "cucumber-js --tags=@release --fail-fast --format progress --format-options '{\"colorsEnabled\": true}' test/bdd/ --import test/bdd/steps/", "test:bdd:publish-errors": "cucumber-js --tags=@publish-errors --fail-fast --format progress --format-options '{\"colorsEnabled\": true}' test/bdd/ --import test/bdd/steps/", "test:bdd:update-errors": "cucumber-js --tags=@update-errors --fail-fast --format progress --format-options '{\"colorsEnabled\": true}' test/bdd/ --import test/bdd/steps/", diff --git a/src/modules/validation/validation-module-manager.js b/src/modules/validation/validation-module-manager.js index ce99f66cce..8f326905ae 100644 --- a/src/modules/validation/validation-module-manager.js +++ b/src/modules/validation/validation-module-manager.js @@ -7,25 +7,44 @@ class ValidationModuleManager extends BaseModuleManager { calculateRoot(assertion) { if (this.initialized) { + if (!assertion) { + throw new Error('Calculation failed: Assertion cannot be null or undefined.'); + } return this.getImplementation().module.calculateRoot(assertion); } + throw new Error('Validation module is not initialized.'); } getMerkleProof(assertion, index) { if (this.initialized) { + if (!assertion) { + throw new Error('Get merkle proof failed: Assertion cannot be null or undefined.'); + } return this.getImplementation().module.getMerkleProof(assertion, index); } + throw new Error('Validation module is not initialized.'); } getHashFunctionName(hashFunctionId) { if (this.initialized) { + if (!hashFunctionId) { + throw new Error( + 'Getting function name failed: Function ID cannot be null or undefined.', + ); + } return this.getImplementation().module.getHashFunctionName(hashFunctionId); } + throw new Error('Validation module is not initialized.'); } async callHashFunction(hashFunctionId, data) { if (this.initialized) { - return this.getImplementation().module.callHashFunction(hashFunctionId, data); + if (!!hashFunctionId && !!data) { + return this.getImplementation().module.callHashFunction(hashFunctionId, data); + } + throw new Error('Calling hash fn failed: Values cannot be null or undefined.'); + } else { + throw new Error('Validation module is not initialized.'); } } } diff --git a/test/modules/repository/config.json b/test/unit/modules/repository/config.json similarity index 100% rename from test/modules/repository/config.json rename to test/unit/modules/repository/config.json diff --git a/test/modules/repository/repository.js b/test/unit/modules/repository/repository.test.js similarity index 98% rename from test/modules/repository/repository.js rename to test/unit/modules/repository/repository.test.js index 05955685cc..793c99705f 100644 --- a/test/modules/repository/repository.js +++ b/test/unit/modules/repository/repository.test.js @@ -2,12 +2,12 @@ import { utils } from 'ethers'; import { describe, it, before, beforeEach, afterEach, after } from 'mocha'; import { expect, assert } from 'chai'; import { readFile } from 'fs/promises'; -import Logger from '../../../src/logger/logger.js'; -import RepositoryModuleManager from '../../../src/modules/repository/repository-module-manager.js'; +import Logger from '../../../../src/logger/logger.js'; +import RepositoryModuleManager from '../../../../src/modules/repository/repository-module-manager.js'; let logger; let repositoryModuleManager; -const config = JSON.parse(await readFile('./test/modules/repository/config.json')); +const config = JSON.parse(await readFile('./test/unit/modules/repository/config.json')); const blockchain = 'hardhat'; const createAgreement = ({ @@ -391,7 +391,7 @@ describe('Repository module', () => { } } - describe('test load', () => { + describe.skip('test load', () => { describe('100_000 rows', () => { beforeEach(async function t() { this.timeout(0); diff --git a/test/modules/triple-store/config.json b/test/unit/modules/triple-store/config.json similarity index 100% rename from test/modules/triple-store/config.json rename to test/unit/modules/triple-store/config.json diff --git a/test/modules/triple-store/triple-store.js b/test/unit/modules/triple-store/triple-store.test.js similarity index 100% rename from test/modules/triple-store/triple-store.js rename to test/unit/modules/triple-store/triple-store.test.js diff --git a/test/unit/modules/validation/config.json b/test/unit/modules/validation/config.json new file mode 100644 index 0000000000..406942f078 --- /dev/null +++ b/test/unit/modules/validation/config.json @@ -0,0 +1,14 @@ +{ + "modules":{ + "validation":{ + "enabled":true, + "implementation":{ + "merkle-validation":{ + "enabled":true, + "package":"./validation/implementation/merkle-validation.js", + "config":{} + } + } + } + } +} diff --git a/test/unit/modules/validation/validation-module-manager.test.js b/test/unit/modules/validation/validation-module-manager.test.js new file mode 100644 index 0000000000..4cabe5041a --- /dev/null +++ b/test/unit/modules/validation/validation-module-manager.test.js @@ -0,0 +1,176 @@ +import { describe, it, beforeEach } from 'mocha'; +import { expect, assert } from 'chai'; +import { readFile } from 'fs/promises'; +import { calculateRoot } from 'assertion-tools'; +import ValidationModuleManager from '../../../../src/modules/validation/validation-module-manager.js'; +import Logger from '../../../../src/logger/logger.js'; + +let validationManager; + +const config = JSON.parse(await readFile('./test/unit/modules/validation/config.json', 'utf-8')); +const assertion = [ + { + '@context': 'https://schema.org', + '@id': 'https://tesla.modelX/2321', + '@type': 'Car', + name: 'Tesla Model X', + brand: { + '@type': 'Brand', + name: 'Tesla', + }, + model: 'Model X', + manufacturer: { + '@type': 'Organization', + name: 'Tesla, Inc.', + }, + fuelType: 'Electric', + }, +]; +const invalidValues = [null, undefined]; +const hashFunctionId = 1; +const keyword = + '0xB0D4afd8879eD9F52b28595d31B441D079B2Ca0768e44dc71bf509adfccbea9df949f253afa56796a3a926203f90a1e4914247d3'; + +describe.only('Validation module manager', async () => { + beforeEach('initialize validation module manage', async () => { + validationManager = new ValidationModuleManager({ + config, + logger: new Logger(), + }); + + validationManager.initialized = true; + expect(await validationManager.initialize()).to.be.true; + }); + + it('validates module name is as expected', async () => { + const moduleName = await validationManager.getName(); + + expect(moduleName).to.equal('validation'); + }); + + it('validate successful root hash calculation, expect to be matched', async () => { + const expectedRootHash = calculateRoot(assertion); + const calculatedRootHash = validationManager.calculateRoot(assertion); + + assert(expect(calculatedRootHash).to.exist); + expect(calculatedRootHash).to.equal(expectedRootHash); + }); + + it('root hash cannot be calculated without initialization', async () => { + validationManager.initialized = false; + + try { + validationManager.calculateRoot(assertion); + } catch (error) { + expect(error.message).to.equal('Validation module is not initialized.'); + } + }); + + it('root hash calculation failed when assertion is null or undefined', async () => { + invalidValues.forEach((value) => { + expect(() => validationManager.calculateRoot(value)).to.throw( + Error, + 'Calculation failed: Assertion cannot be null or undefined.', + ); + }); + }); + + it('successful getting merkle proof hash', async () => { + const calculatedMerkleHash = validationManager.getMerkleProof(assertion, 0); + + assert(expect(calculatedMerkleHash).to.exist); + expect(calculatedMerkleHash).to.be.instanceof(Object); + expect(calculatedMerkleHash).to.haveOwnProperty('leaf').and.to.be.a('string'); + expect(calculatedMerkleHash).to.haveOwnProperty('proof').and.to.be.a('array'); + }); + + it('merkle prof hash cannot be calculated without initialization', async () => { + validationManager.initialized = false; + + try { + validationManager.getMerkleProof(assertion, 0); + } catch (error) { + expect(error.message).to.equal('Validation module is not initialized.'); + } + }); + + it('failed merkle prof hash calculation when assertion is null or undefined', async () => { + invalidValues.forEach((value) => { + expect(() => validationManager.getMerkleProof(value, 0)).to.throw( + Error, + 'Get merkle proof failed: Assertion cannot be null or undefined.', + ); + }); + }); + + it('validate getting function name', async () => { + const getFnHashName = validationManager.getHashFunctionName(hashFunctionId); + + assert(expect(getFnHashName).to.exist); + expect(getFnHashName).to.equal('sha256'); + }); + + it('failed getting function name without initialization', async () => { + validationManager.initialized = false; + + try { + validationManager.getHashFunctionName(hashFunctionId); + } catch (error) { + expect(error.message).to.equal('Validation module is not initialized.'); + } + }); + + it('validate successful calling function name', async () => { + const callFunction = await validationManager.callHashFunction(hashFunctionId, keyword); + + assert(expect(callFunction).to.exist); + expect(callFunction).to.be.a('string'); + expect(callFunction).to.equal( + '0x5fe7425e0d956e2cafeac276c3ee8e70f377b2bd14790bc6d4777c3e7ba63b46', + ); + }); + + it('unsuccessful calling function name without initialization', async () => { + validationManager.initialized = false; + + try { + await validationManager.callHashFunction(hashFunctionId, keyword); + } catch (error) { + expect(error.message).to.equal('Validation module is not initialized.'); + } + }); + + it('failed function name initialization when function id is null or undefined', async () => { + async function testInvalidValues() { + for (const value of invalidValues) { + try { + // eslint-disable-next-line no-await-in-loop + await validationManager.getMerkleProof(value, 0); + } catch (error) { + expect(error.message).to.equal( + 'Get merkle proof failed: Assertion cannot be null or undefined.', + ); + } + } + } + + await testInvalidValues(); + }); + + it('failed function name initialization when data is null or undefined', async () => { + async function testInvalidValues() { + for (const value of invalidValues) { + try { + // eslint-disable-next-line no-await-in-loop + await validationManager.callHashFunction(value, 0); + } catch (error) { + expect(error.message).to.equal( + 'Calling hash fn failed: Values cannot be null or undefined.', + ); + } + } + } + + await testInvalidValues(); + }); +});