From 7e251dc01a988d35aee7bb9c3c6bbffbf9541bd3 Mon Sep 17 00:00:00 2001 From: Matthew Dean Date: Tue, 19 Dec 2023 09:50:26 +0000 Subject: [PATCH] Feature/manual seal (#44) * Add support in tests for using manual seal * 0.7.0 * Linting fix * Update workflows to use correct compose file --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- README.md | 21 +++++- docker-compose-test.yml | 78 ++++++++++++++++++++ package-lock.json | 4 +- package.json | 2 +- src/lib/chainNode.ts | 4 + test/helpers/chainTest.ts | 44 +++++------ test/integration/onchain/certificate.test.ts | 4 + test/integration/onchain/chain.test.ts | 1 + 10 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 docker-compose-test.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f7f8c3b..28cbc1e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -100,7 +100,7 @@ jobs: run: npm run build - name: Setup dependencies if: matrix.test-type != 'unit' - run: docker-compose up -d + run: docker-compose -f ./docker-compose-test.yml up -d - name: Sleep if: matrix.test-type != 'unit' uses: kibertoad/wait-action@1.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4289be5..b4b4299 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -91,7 +91,7 @@ jobs: run: npm run build - name: Setup dependencies if: matrix.test-type != 'unit' - run: docker-compose up -d + run: docker-compose -f ./docker-compose-test.yml up -d - name: Sleep if: matrix.test-type != 'unit' uses: kibertoad/wait-action@1.0.1 diff --git a/README.md b/README.md index e245919..9871060 100644 --- a/README.md +++ b/README.md @@ -68,16 +68,29 @@ npx knex migrate:make --knexfile src/lib/db/knexfile.ts attachment-table ## Tests -Integration tests are executed by calling: +Unit tests are executed by calling: ```sh -npm run test +npm run test:unit ``` -Unit tests are executed by calling: +Integration tests require the test dependency services be brought up using docker: ```sh -npm run test:unit +# start dependencies +docker compose -f ./docker-compose-test.yml up -d +# install packages +npm ci +# run migrations +npm run db:migrate +# put process flows on-chain +npm run flows +``` + +Integration tests are then executed by calling: + +```sh +npm run test ``` ## Process Flows diff --git a/docker-compose-test.yml b/docker-compose-test.yml new file mode 100644 index 0000000..dce49d5 --- /dev/null +++ b/docker-compose-test.yml @@ -0,0 +1,78 @@ +version: '3' + +services: + postgres-hyproof-api: + image: postgres:16.1-alpine + container_name: postgres-hyproof-api + ports: + - 5432:5432 + volumes: + - hyproof-api-storage:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=postgres + - POSTGRES_USER=postgres + - POSTGRES_DB=dscp-hyproof-api + + postgres-identity-service: + image: postgres:16.1-alpine + container_name: postgres-identity + ports: + - 5433:5432 + volumes: + - identity-storage:/var/lib/postgresql/data + environment: + - POSTGRES_PASSWORD=postgres + - POSTGRES_USER=postgres + - POSTGRES_DB=dscp-identity-service + + dscp-identity-service: + image: digicatapult/dscp-identity-service:latest + container_name: identity-service + command: /bin/sh -c " + sleep 30 && + npx knex migrate:latest && + node app/index.js" + ports: + - 3002:3002 + environment: + - PORT=3002 + - API_HOST=dscp-node + - DB_HOST=postgres-identity-service + - DB_PORT=5432 + - DB_NAME=dscp-identity-service + - DB_USERNAME=postgres + - DB_PASSWORD=postgres + - SELF_ADDRESS=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY + - AUTH_TYPE=${AUTH_TYPE:-NONE} + + dscp-node: + image: digicatapult/dscp-node:latest + container_name: node + command: --base-path /data/ + --dev + --manual-seal + --unsafe-ws-external + --unsafe-rpc-external + --ws-max-connections 512 + --rpc-cors all + ports: + - 30333:30333 + - 9944:9944 + - 9933:9933 + restart: on-failure + + ipfs: + image: ipfs/go-ipfs:v0.24.0 + container_name: ipfs + environment: + - | + IPFS_SWARM_KEY=/key/swarm/psk/1.0.0/ + /base16/ + 0000000000000000000000000000000000000000000000000000000000000000 + ports: + - 4001:4001 + - 8080:8080 + - 5001:5001 +volumes: + hyproof-api-storage: + identity-storage: diff --git a/package-lock.json b/package-lock.json index 67fabe2..c6e3190 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@digicatapult/dscp-hyproof-api", - "version": "0.6.5", + "version": "0.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@digicatapult/dscp-hyproof-api", - "version": "0.6.5", + "version": "0.7.0", "license": "Apache-2.0", "dependencies": { "@polkadot/api": "^10.11.1", diff --git a/package.json b/package.json index 7f4f7ff..0f25095 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@digicatapult/dscp-hyproof-api", - "version": "0.6.5", + "version": "0.7.0", "description": "An OpenAPI API service for DSCP", "main": "src/index.ts", "scripts": { diff --git a/src/lib/chainNode.ts b/src/lib/chainNode.ts index 746f75b..1db8139 100644 --- a/src/lib/chainNode.ts +++ b/src/lib/chainNode.ts @@ -294,4 +294,8 @@ export default class ChainNode { roles, } } + + async sealBlock(createEmpty: boolean = true, finalise: boolean = true) { + return await this.api.rpc.engine.createBlock(createEmpty, finalise) + } } diff --git a/test/helpers/chainTest.ts b/test/helpers/chainTest.ts index 3f3a64a..2c98f9f 100644 --- a/test/helpers/chainTest.ts +++ b/test/helpers/chainTest.ts @@ -12,9 +12,28 @@ import { logger } from '../../src/lib/logger' import { put } from './routeHelper' import { mockEnv, notSelfAddress, regulatorAddress, selfAddress } from './mock' import { processInitiateCert, processIssueCert } from '../../src/lib/payload' +import { SubmittableExtrinsic } from '@polkadot/api/types' +import { SubmittableResult } from '@polkadot/api' const db = new Database() +const submitRunProcessExtrinsicAndSeal = async ( + node: ChainNode, + extrinsic: SubmittableExtrinsic<'promise', SubmittableResult> +): Promise => { + return new Promise((resolve, reject) => { + node + .submitRunProcess(extrinsic, (state, outputs) => { + if (state === 'finalised') { + setTimeout(() => resolve(outputs ? outputs : []), 100) + } else if (state === 'failed') reject() + }) + .then(() => { + node.sealBlock() + }) + }) +} + export const withAppAndIndexer = (context: { app: Express; indexer: Indexer }) => { before(async function () { context.app = await createHttpServer() @@ -64,13 +83,7 @@ export const withInitialisedCertFromNotSelf = async (context: { app: Express; db } as CertificateRow) ) - const tokenId = await new Promise((resolve, reject) => { - node.submitRunProcess(extrinsic, (state, outputs) => { - if (state === 'finalised') { - setTimeout(() => resolve(outputs ? outputs[0] : Number.NaN), 100) - } else if (state === 'failed') reject() - }) - }) + const [tokenId] = await submitRunProcessExtrinsicAndSeal(node, extrinsic) const [{ id }] = await db.get('certificate', { latest_token_id: tokenId }) @@ -107,13 +120,7 @@ export const withIssuedCertAsRegulator = async (context: { app: Express; db: Dat } as CertificateRow) ) - const initTokenId = await new Promise((resolve, reject) => { - heidiNode.submitRunProcess(initExtrinsic, (state, outputs) => { - if (state === 'finalised') { - setTimeout(() => resolve(outputs ? outputs[0] : Number.NaN), 100) - } else if (state === 'failed') reject() - }) - }) + const [initTokenId] = await submitRunProcessExtrinsicAndSeal(heidiNode, initExtrinsic) const emmaNode = new ChainNode( mockEnv({ @@ -133,14 +140,7 @@ export const withIssuedCertAsRegulator = async (context: { app: Express; db: Dat } as CertificateRow) ) - const issuedTokenId = await new Promise((resolve, reject) => { - emmaNode.submitRunProcess(issueExtrinsic, (state, outputs) => { - if (state === 'finalised') { - setTimeout(() => resolve(outputs ? outputs[0] : Number.NaN), 100) - } else if (state === 'failed') reject() - }) - }) - + const [issuedTokenId] = await submitRunProcessExtrinsicAndSeal(emmaNode, issueExtrinsic) const [cert] = await db.get('certificate', { latest_token_id: issuedTokenId }) context.cert = cert } diff --git a/test/integration/onchain/certificate.test.ts b/test/integration/onchain/certificate.test.ts index ef956cf..28f1aff 100644 --- a/test/integration/onchain/certificate.test.ts +++ b/test/integration/onchain/certificate.test.ts @@ -73,6 +73,7 @@ describe('on-chain', function () { ) expect(state).to.equal('submitted') + await node.sealBlock() await pollTransactionState(db, transactionId, 'finalised') const [cert] = await db.get('certificate', { id: certId }) @@ -112,6 +113,7 @@ describe('on-chain', function () { ) expect(state).to.equal('submitted') + await node.sealBlock() await pollTransactionState(db, transactionId, 'finalised') const [cert] = await db.get('certificate', { id: context.cert.id }) @@ -138,6 +140,7 @@ describe('on-chain', function () { ) expect(state).to.equal('submitted') + await node.sealBlock() await pollTransactionState(db, transactionId, 'finalised') const [cert] = await db.get('certificate', { id: context.cert.id }) @@ -166,6 +169,7 @@ describe('on-chain', function () { ) expect(state).to.equal('submitted') + await node.sealBlock() await pollTransactionState(db, transactionId, 'finalised') const [cert] = await db.get('certificate', { id: context.cert.id }) diff --git a/test/integration/onchain/chain.test.ts b/test/integration/onchain/chain.test.ts index 9f8b8e4..1f0f629 100644 --- a/test/integration/onchain/chain.test.ts +++ b/test/integration/onchain/chain.test.ts @@ -43,6 +43,7 @@ describe('on-chain', function () { node.submitRunProcess(extrinsic, (state) => db.update('transaction', { id: transaction.id }, { state })) // wait for dispatch error + await node.sealBlock() const failedTransaction = await pollTransactionState(db, transaction.id, 'failed') expect(failedTransaction.state).to.equal('failed') })