Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Added Unit Test for RegisterAuthority
Browse files Browse the repository at this point in the history
  • Loading branch information
Phanco committed May 26, 2023
1 parent 9fbe3fc commit b6be097
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 29 deletions.
10 changes: 5 additions & 5 deletions framework/src/modules/poa/commands/register_authority.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,19 @@ export class RegisterAuthorityCommand extends BaseCommand {
};
}

if (!name || name === '' || !/^[a-z0-9!@$&_.]+$/g.test(name)) {
if (!/^[a-z0-9!@$&_.]+$/g.test(name)) {
throw new Error('Invalid name');
}

const isNameExist = await this.stores.get(ValidatorStore).has(context, Buffer.from(name));
const isNameExist = await this.stores.get(NameStore).has(context, Buffer.from(name));
if (isNameExist) {
throw new Error('name exist');
throw new Error('name already exist');
}

const senderAddress = getSenderAddress(context.transaction.senderPublicKey);
const isValidatorExist = await this.stores.get(NameStore).has(context, senderAddress);
const isValidatorExist = await this.stores.get(ValidatorStore).has(context, senderAddress);
if (isValidatorExist) {
throw new Error('validator exist');
throw new Error('validator already exist');
}

return {
Expand Down
2 changes: 1 addition & 1 deletion framework/src/modules/poa/stores/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const validatorNameSchema = {
required: ['name'],
properties: {
name: {
type: 'string',
dataType: 'string',
fieldNumber: 1,
minLength: 1,
maxLength: MAX_LENGTH_NAME,
Expand Down
134 changes: 111 additions & 23 deletions framework/test/unit/modules/poa/commands/register_authority.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,46 +12,68 @@
* Removal or modification of this copyright notice is prohibited.
*/

import { TransactionAttrs } from '@liskhq/lisk-chain';
import { codec } from '@liskhq/lisk-codec';
import { utils } from '@liskhq/lisk-cryptography';
import * as testing from '../../../../../src/testing';
import { Transaction, VerifyStatus } from '../../../../../src';
import {
CommandExecuteContext,
CommandVerifyContext,
Transaction,
VerifyStatus,
PoAModule,
} from '../../../../../src';
import { RegisterAuthorityCommand } from '../../../../../src/modules/poa/commands/register_authority';
import { PoAModule } from '../../../../../src';
import { ValidatorsMethod } from '../../../../../dist-node/modules/pos/types';
import { FeeMethod } from '../../../../../dist-node/modules/interoperability/types';
import { COMMAND_REGISTER_AUTHORITY } from '../../../../../dist-node/modules/poa/constants';
import { ValidatorsMethod } from '../../../../../src/modules/pos/types';
import { FeeMethod } from '../../../../../src/modules/interoperability/types';
import {
COMMAND_REGISTER_AUTHORITY,
REGISTRATION_FEE,
} from '../../../../../src/modules/poa/constants';

import { registerAuthorityParamsSchema } from '../../../../../src/modules/poa/schemas';
import { RegisterAuthorityParams } from '../../../../../src/modules/poa/types';

import { createStoreGetter } from '../../../../../src/testing/utils';
import { NameStore, ValidatorStore } from '../../../../../src/modules/poa/stores';
import { PrefixedStateReadWriter } from '../../../../../src/state_machine/prefixed_state_read_writer';
import { InMemoryPrefixedStateDB } from '../../../../../src/testing';
import { getSenderAddress } from '../../../../../src/modules/poa/utils';

describe('RegisterAuthority', () => {
const poa = new PoAModule();
let registerAuthorityCommand: RegisterAuthorityCommand;
let mockValidatorsMethod: ValidatorsMethod;
let mockFeeMethod: FeeMethod;
let stateStore: PrefixedStateReadWriter;
let validatorSubstore: ValidatorStore;
let nameSubstore: NameStore;

const transactionParams = {
name: 'max',
blsKey: utils.getRandomBytes(48),
proofOfPossession: utils.getRandomBytes(96),
generatorKey: utils.getRandomBytes(32),
};

const publicKey = utils.getRandomBytes(32);
const transaction = new Transaction({
module: 'poa',
command: COMMAND_REGISTER_AUTHORITY,
senderPublicKey: publicKey,
nonce: BigInt(0),
fee: BigInt(1000000000),
params: codec.encode(registerAuthorityParamsSchema, transactionParams),
signatures: [publicKey],
});
const chainID = Buffer.from(
'e48feb88db5b5cf5ad71d93cdcd1d879b6d5ed187a36b0002cc34e0ef9883255',
'hex',
);

const buildTransaction = (transaction: Partial<TransactionAttrs>): Transaction => {
return new Transaction({
module: transaction.module ?? 'poa',
command: transaction.command ?? COMMAND_REGISTER_AUTHORITY,
senderPublicKey: transaction.senderPublicKey ?? publicKey,
nonce: transaction.nonce ?? BigInt(0),
fee: transaction.fee ?? BigInt(1000000000),
params: transaction.params ?? codec.encode(registerAuthorityParamsSchema, transactionParams),
signatures: transaction.signatures ?? [publicKey],
});
};

beforeEach(() => {
registerAuthorityCommand = new RegisterAuthorityCommand(poa.stores, poa.events);
mockValidatorsMethod = {
Expand All @@ -66,29 +88,95 @@ describe('RegisterAuthority', () => {
payFee: jest.fn(),
};
registerAuthorityCommand.addDependencies(mockValidatorsMethod, mockFeeMethod);

stateStore = new PrefixedStateReadWriter(new InMemoryPrefixedStateDB());
validatorSubstore = poa.stores.get(ValidatorStore);
nameSubstore = poa.stores.get(NameStore);
});

describe('verify', () => {
it('should return error when name is empty', async () => {
const context = testing
let context: CommandVerifyContext<RegisterAuthorityParams>;
beforeEach(() => {
context = testing
.createTransactionContext({
transaction,
stateStore,
transaction: buildTransaction({}),
chainID,
})
.createCommandVerifyContext<RegisterAuthorityParams>(registerAuthorityParamsSchema);
});

it('should return error when name does not comply regex', async () => {
context = testing
.createTransactionContext({
stateStore,
transaction: buildTransaction({
params: codec.encode(registerAuthorityParamsSchema, {
...transactionParams,
name: '###',
}),
}),
chainID,
})
.createCommandVerifyContext<RegisterAuthorityParams>(registerAuthorityParamsSchema);
const result = await registerAuthorityCommand.verify(context);

expect(result.status).toBe(VerifyStatus.FAIL);
await expect(registerAuthorityCommand.verify(context)).rejects.toThrow('Invalid name');
});

it('should return error when name does not comply regex', async () => {});
it('should return error when name already exist', async () => {
await nameSubstore.set(createStoreGetter(stateStore), Buffer.from(transactionParams.name), {
address: getSenderAddress(context.transaction.senderPublicKey),
});

it('should return error when name already exist', async () => {});
await expect(registerAuthorityCommand.verify(context)).rejects.toThrow('name already exist');
});

it('should return error when senderAddress already exist', async () => {
await validatorSubstore.set(createStoreGetter(stateStore), getSenderAddress(publicKey), {
name: transactionParams.name,
});

await expect(registerAuthorityCommand.verify(context)).rejects.toThrow(
'validator already exist',
);
});

it('should return error when senderAddress already exist', async () => {});
it('should return OK when transaction is valid', async () => {
const result = await registerAuthorityCommand.verify(context);

expect(result.status).toBe(VerifyStatus.OK);
});
});

describe('execute', () => {
it('should call registerValidatorKeys', async () => {});
let context: CommandExecuteContext<RegisterAuthorityParams>;
beforeEach(() => {
context = testing
.createTransactionContext({
stateStore,
transaction: buildTransaction({}),
chainID,
})
.createCommandExecuteContext(registerAuthorityParamsSchema);
});

it('should call registerValidatorKeys', async () => {
await registerAuthorityCommand.execute(context);

expect(mockFeeMethod.payFee).toHaveBeenCalledWith(expect.anything(), REGISTRATION_FEE);
await expect(
validatorSubstore.has(createStoreGetter(stateStore), getSenderAddress(publicKey)),
).resolves.toBe(true);
await expect(
nameSubstore.has(createStoreGetter(stateStore), Buffer.from(transactionParams.name)),
).resolves.toBe(true);
expect(mockValidatorsMethod.registerValidatorKeys).toHaveBeenCalledWith(
expect.anything(),
getSenderAddress(publicKey),
context.params.proofOfPossession,
context.params.generatorKey,
context.params.blsKey,
);
});
});
});

0 comments on commit b6be097

Please sign in to comment.