Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v6: Unit tests for validation module manager #2663

Merged
merged 12 commits into from
Nov 14, 2023
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/",
Expand Down
21 changes: 20 additions & 1 deletion src/modules/validation/validation-module-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ({
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions test/unit/modules/validation/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"modules":{
"validation":{
"enabled":true,
"implementation":{
"merkle-validation":{
"enabled":true,
"package":"./validation/implementation/merkle-validation.js",
"config":{}
}
}
}
}
}
176 changes: 176 additions & 0 deletions test/unit/modules/validation/validation-module-manager.test.js
Original file line number Diff line number Diff line change
@@ -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);
AnaDjokovic marked this conversation as resolved.
Show resolved Hide resolved
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();
});
});