From ca0592b09bd8317a0f3d583aac4d6559e9cceb98 Mon Sep 17 00:00:00 2001 From: David Poltorak Date: Mon, 9 Oct 2023 13:05:50 +0100 Subject: [PATCH] feat: fix all performance test flows and set group thresholds Signed-off-by: David Poltorak --- .github/workflows/performance-tests.yml | 17 +++-- .../atala-performance-tests-k6/package.json | 3 +- .../src/common/ConnectionService.ts | 10 ++- .../src/common/CredentialsService.ts | 21 ++--- .../src/common/DidService.ts | 13 ++-- .../src/common/HttpService.ts | 4 + .../src/common/ProofsService.ts | 8 +- .../src/scenarios/default.ts | 31 ++++++++ .../credentials/credential-offer-test.ts | 48 +++++------- .../credentials/credential-schema-test.ts | 38 ++++------ .../src/tests/dids/create-prism-did-test.ts | 26 +++---- .../src/tests/dids/did-publishing-test.ts | 28 ++++--- .../src/tests/flows/connection-flow-test.ts | 39 +++++----- .../src/tests/flows/full-flow-test.ts | 62 --------------- .../src/tests/flows/issuance-flow-test.ts | 76 ++++++++++--------- .../tests/flows/present-proof-flow-test.ts | 62 ++++++++------- .../atala-performance-tests-k6/yarn.lock | 5 ++ 17 files changed, 230 insertions(+), 261 deletions(-) create mode 100644 tests/performance-tests/atala-performance-tests-k6/src/scenarios/default.ts delete mode 100644 tests/performance-tests/atala-performance-tests-k6/src/tests/flows/full-flow-test.ts diff --git a/.github/workflows/performance-tests.yml b/.github/workflows/performance-tests.yml index 2b9190c222..9eee243106 100644 --- a/.github/workflows/performance-tests.yml +++ b/.github/workflows/performance-tests.yml @@ -6,9 +6,6 @@ concurrency: on: pull_request: - paths: - - ".github/workflows/performance-tests.yml" - - "tests/performance-tests/**" push: branches: - "main" @@ -90,18 +87,18 @@ jobs: scope: 'input-output-hk' - name: Install dependencies - uses: borales/actions-yarn@v4 + uses: borales/actions-yarn@v4.2.0 with: cmd: install dir: ${{ env.BENCHMARKING_DIR }} - name: Compile tests to JS - uses: borales/actions-yarn@v4 + uses: borales/actions-yarn@v4.2.0 with: cmd: webpack dir: ${{ env.BENCHMARKING_DIR }} - - name: Connection Flow Smoke Test + - name: All Smoke Tests env: ISSUER_AGENT_API_KEY: default HOLDER_AGENT_API_KEY: default @@ -109,4 +106,10 @@ jobs: # Have to use manual download because GitHub action doesnt support localhost execution curl https://github.com/grafana/k6/releases/download/v0.45.0/k6-v0.45.0-linux-amd64.tar.gz -L | tar xvz --strip-components 1 ls -la - ./k6 run ${{ env.BENCHMARKING_DIR }}/dist/connection-flow-test.js + ./k6 run -e SCENARIO_LABEL=create-prism-did-smoke ${{ env.BENCHMARKING_DIR }}/dist/create-prism-did-test.js + ./k6 run -e SCENARIO_LABEL=credential-offer-smoke ${{ env.BENCHMARKING_DIR }}/dist/credential-offer-test.js + ./k6 run -e SCENARIO_LABEL=credential-schema-smoke ${{ env.BENCHMARKING_DIR }}/dist/credential-schema-test.js + ./k6 run -e SCENARIO_LABEL=did-publishing-smoke ${{ env.BENCHMARKING_DIR }}/dist/did-publishing-test.js + ./k6 run -e SCENARIO_LABEL=connection-flow-smoke ${{ env.BENCHMARKING_DIR }}/dist/connection-flow-test.js + ./k6 run -e SCENARIO_LABEL=issuance-flow-smoke ${{ env.BENCHMARKING_DIR }}/dist/issuance-flow-test.js + ./k6 run -e SCENARIO_LABEL=present-proof-flow-smoke ${{ env.BENCHMARKING_DIR }}/dist/present-proof-flow-test.js diff --git a/tests/performance-tests/atala-performance-tests-k6/package.json b/tests/performance-tests/atala-performance-tests-k6/package.json index 8b8e498d7e..c7d543ed60 100644 --- a/tests/performance-tests/atala-performance-tests-k6/package.json +++ b/tests/performance-tests/atala-performance-tests-k6/package.json @@ -19,7 +19,8 @@ "typescript": "5.2.2", "webpack": "5.88.2", "webpack-cli": "5.1.4", - "webpack-glob-entries": "^1.0.1" + "webpack-glob-entries": "^1.0.1", + "ts-deepmerge": "6.2.0" }, "scripts": { "start": "webpack" diff --git a/tests/performance-tests/atala-performance-tests-k6/src/common/ConnectionService.ts b/tests/performance-tests/atala-performance-tests-k6/src/common/ConnectionService.ts index 59e1cea9a6..d43acd6678 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/common/ConnectionService.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/common/ConnectionService.ts @@ -1,3 +1,5 @@ +/*global __ENV*/ + import { Connection, ConnectionInvitation, ConnectionStateEnum } from "@input-output-hk/prism-typescript-client"; import { WAITING_LOOP_MAX_ITERATIONS, WAITING_LOOP_PAUSE_INTERVAL } from "./Config"; import { HttpService } from "./HttpService"; @@ -26,7 +28,7 @@ export class ConnectionService extends HttpService { */ getConnection(connectionId: string): Connection { const res = this.get(`connections/${connectionId}`); - const connection = res.json() as unknown as Connection; + const connection = this.toJson(res) as unknown as Connection; return connection; } @@ -36,7 +38,7 @@ export class ConnectionService extends HttpService { */ createConnection(): Connection { const payload = { label: "test" }; - const connection = this.post("connections", payload).json() as unknown as Connection; + const connection = this.toJson(this.post("connections", payload)) as unknown as Connection; return connection; } @@ -48,7 +50,7 @@ export class ConnectionService extends HttpService { acceptConnectionInvitation(invitation: ConnectionInvitation): Connection { const payload = { invitation: this.invitationFromUrl(invitation.invitationUrl) }; const res = this.post("connection-invitations", payload, 200); - return res.json() as unknown as Connection; + return this.toJson(res) as unknown as Connection; } /** @@ -66,7 +68,7 @@ export class ConnectionService extends HttpService { sleep(WAITING_LOOP_PAUSE_INTERVAL); iterations++; } while (state !== requiredState && iterations < WAITING_LOOP_MAX_ITERATIONS); - if (state != requiredState) { + if (state !== requiredState) { throw new Error(`Connection state is ${state}, required ${requiredState}`); } } diff --git a/tests/performance-tests/atala-performance-tests-k6/src/common/CredentialsService.ts b/tests/performance-tests/atala-performance-tests-k6/src/common/CredentialsService.ts index 8961b64b9a..c55a37ca1d 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/common/CredentialsService.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/common/CredentialsService.ts @@ -2,7 +2,8 @@ import { sleep } from "k6"; import { HttpService } from "./HttpService"; import { ISSUER_AGENT_URL, WAITING_LOOP_MAX_ITERATIONS, WAITING_LOOP_PAUSE_INTERVAL } from "./Config"; import { IssueCredentialRecord, Connection, CredentialSchemaResponse } from "@input-output-hk/prism-typescript-client"; -import {v4 as uuidv4} from 'uuid'; +import { crypto } from "k6/experimental/webcrypto"; + /** * A service class for managing credentials in the application. @@ -18,8 +19,8 @@ export class CredentialsService extends HttpService { */ createCredentialOffer(issuingDid: string, connection: Connection, schema: CredentialSchemaResponse): IssueCredentialRecord { const payload = `{ - "claims": { - "emailAddress": "${uuidv4()}-@atala.io", + "claims": { + "emailAddress": "${crypto.randomUUID()}-@atala.io", "familyName": "Test", "dateOfIssuance": "${new Date()}", "drivingLicenseID": "Test", @@ -31,13 +32,13 @@ export class CredentialsService extends HttpService { "automaticIssuance": false }`; const res = this.post("issue-credentials/credential-offers", payload); - return res.json() as unknown as IssueCredentialRecord; + return this.toJson(res) as unknown as IssueCredentialRecord; } createCredentialSchema(issuingDid: string): CredentialSchemaResponse { const payload = ` { - "name": "${uuidv4()}}", + "name": "${crypto.randomUUID()}}", "version": "1.0.0", "description": "Simple credential schema for the driving licence verifiable credential.", "type": "https://w3c-ccg.github.io/vc-json-schemas/schema/2.0/schema.json", @@ -85,7 +86,7 @@ export class CredentialsService extends HttpService { } ` const res = this.post("schema-registry/schemas", payload); - return res.json() as unknown as CredentialSchemaResponse; + return this.toJson(res) as unknown as CredentialSchemaResponse; } /** @@ -95,7 +96,7 @@ export class CredentialsService extends HttpService { */ getCredentialRecord(record: IssueCredentialRecord): IssueCredentialRecord { const res = this.get(`issue-credentials/records/${record.recordId}`); - return res.json() as unknown as IssueCredentialRecord; + return this.toJson(res) as unknown as IssueCredentialRecord; } /** @@ -104,7 +105,7 @@ export class CredentialsService extends HttpService { */ getCredentialRecords(thid: string): IssueCredentialRecord[] { const res = this.get(`issue-credentials/records?thid=${thid}`); - return res.json("contents") as unknown as IssueCredentialRecord[]; + return this.toJson(res).contents as unknown as IssueCredentialRecord[]; } /** @@ -116,7 +117,7 @@ export class CredentialsService extends HttpService { acceptCredentialOffer(record: IssueCredentialRecord, subjectDid: string): IssueCredentialRecord { const payload = { subjectId: subjectDid }; const res = this.post(`issue-credentials/records/${record.recordId}/accept-offer`, payload, 200); - return res.json() as unknown as IssueCredentialRecord; + return this.toJson(res) as unknown as IssueCredentialRecord; } /** @@ -126,7 +127,7 @@ export class CredentialsService extends HttpService { */ issueCredential(record: IssueCredentialRecord): IssueCredentialRecord { const res = this.post(`issue-credentials/records/${record.recordId}/issue-credential`, null, 200); - return res.json() as unknown as IssueCredentialRecord; + return this.toJson(res) as unknown as IssueCredentialRecord; } /** diff --git a/tests/performance-tests/atala-performance-tests-k6/src/common/DidService.ts b/tests/performance-tests/atala-performance-tests-k6/src/common/DidService.ts index c203bf0af6..95f1cc60c8 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/common/DidService.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/common/DidService.ts @@ -1,7 +1,10 @@ +/*global __ENV*/ + import { HttpService } from "./HttpService"; import { WAITING_LOOP_MAX_ITERATIONS, WAITING_LOOP_PAUSE_INTERVAL } from "./Config"; import { CreateManagedDIDResponse, DIDDocument, DidOperationSubmission, ManagedDID } from "@input-output-hk/prism-typescript-client"; -import { sleep } from "k6"; +import {sleep} from "k6"; + /** * A service class for managing decentralized identifiers (DIDs) in the application. @@ -16,7 +19,7 @@ export class DidService extends HttpService { */ getDid(did: string): ManagedDID { const res = this.get(`did-registrar/dids/${did}`); - return res.json() as unknown as ManagedDID; + return this.toJson(res) as unknown as ManagedDID; } /** @@ -26,7 +29,7 @@ export class DidService extends HttpService { */ resolveDid(did: string): DIDDocument { const res = this.get(`dids/${did}`); - return res.json() as unknown as DIDDocument; + return this.toJson(res) as unknown as DIDDocument; } /** @@ -36,7 +39,7 @@ export class DidService extends HttpService { */ publishDid(did: string): DidOperationSubmission { const res = this.post(`did-registrar/dids/${did}/publications`, null, 202); - return res.json("scheduledOperation") as unknown as DidOperationSubmission; + return this.toJson(res).scheduledOperation as unknown as DidOperationSubmission; } /** @@ -46,7 +49,7 @@ export class DidService extends HttpService { */ createUnpublishedDid(documentTemplate: string): CreateManagedDIDResponse { const res = this.post("did-registrar/dids", documentTemplate); - return res.json() as unknown as CreateManagedDIDResponse; + return this.toJson(res) as unknown as CreateManagedDIDResponse; } /** diff --git a/tests/performance-tests/atala-performance-tests-k6/src/common/HttpService.ts b/tests/performance-tests/atala-performance-tests-k6/src/common/HttpService.ts index 422652c11a..4b98159cc1 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/common/HttpService.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/common/HttpService.ts @@ -34,6 +34,10 @@ export class HttpService { }; } + public toJson(response: RefinedResponse): any { + return JSON.parse(response.body as string) + } + /** * Performs an HTTP POST request to the specified endpoint with the provided payload. * @param endpoint The API endpoint to post to. diff --git a/tests/performance-tests/atala-performance-tests-k6/src/common/ProofsService.ts b/tests/performance-tests/atala-performance-tests-k6/src/common/ProofsService.ts index b52c723a25..f274b8f0de 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/common/ProofsService.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/common/ProofsService.ts @@ -34,7 +34,7 @@ export class ProofsService extends HttpService { ] }` const res = this.post("present-proof/presentations", payload); - return res.json("presentationId") as string; + return this.toJson(res).presentationId as string; } /** @@ -51,7 +51,7 @@ export class ProofsService extends HttpService { ] }` const res = this.patch(`present-proof/presentations/${presentation.presentationId}`, payload); - return res.json("presentationId") as string; + return this.toJson(res).presentationId as string; } /** @@ -61,7 +61,7 @@ export class ProofsService extends HttpService { */ getPresentation(presentationId: string): PresentationStatus { const res = this.get(`present-proof/presentations/${presentationId}`); - return res.json() as unknown as PresentationStatus; + return this.toJson(res) as unknown as PresentationStatus; } /** @@ -70,7 +70,7 @@ export class ProofsService extends HttpService { */ getPresentations(thid: string): PresentationStatus[] { const res = this.get(`present-proof/presentations?thid=${thid}`); - return res.json("contents") as unknown as PresentationStatus[]; + return this.toJson(res).contents as unknown as PresentationStatus[]; } /** diff --git a/tests/performance-tests/atala-performance-tests-k6/src/scenarios/default.ts b/tests/performance-tests/atala-performance-tests-k6/src/scenarios/default.ts new file mode 100644 index 0000000000..28332cdd92 --- /dev/null +++ b/tests/performance-tests/atala-performance-tests-k6/src/scenarios/default.ts @@ -0,0 +1,31 @@ +/*global __ENV*/ + +import { Options } from "k6/options"; + +export const defaultOptions: Options = { + setupTimeout: '120s', + scenarios: { + smoke: { + // a simple test to ensure performance tests work and requests don't fail + executor: "shared-iterations", + vus: 1, + iterations: 1, + tags: { scenario_label: __ENV.SCENARIO_LABEL || "defaultScenarioLabel" }, // add label for filtering in observability platform + }, + }, + thresholds: { + http_req_failed: [ + // fail if any requests fail during smoke test + { + threshold: "rate==0", + abortOnFail: true, + }, + ], + http_req_duration: [ + { threshold: "p(95)<2000", abortOnFail: true }, // 95% of requests should complete within 2 seconds + { threshold: "p(99)<5000", abortOnFail: true }, // 99% of requests should complete within 5 seconds + ], + checks: [{ threshold: "rate==1", abortOnFail: true }], // fail if any checks fail (the checks are defined in test code which is executed) + + } +} diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-offer-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-offer-test.ts index 27b86d07ff..4a02f90bc2 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-offer-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-offer-test.ts @@ -1,37 +1,16 @@ import { group } from 'k6'; import { Options } from 'k6/options'; import { Issuer, Holder } from '../../actors'; -import { Connection } from '@input-output-hk/prism-typescript-client'; +import { Connection, CredentialSchemaResponse } from '@input-output-hk/prism-typescript-client'; +import { defaultOptions } from "../../scenarios/default"; +import merge from "ts-deepmerge"; -// export let options: Options = { -// stages: [ -// { duration: '1m', target: 5 }, -// ], -// thresholds: { -// http_req_failed: [{ -// threshold: 'rate<=0.05', -// abortOnFail: true, -// }], -// http_req_duration: ['p(95)<=100'], -// checks: ['rate>=0.99'], -// }, -// }; - -export let options: Options = { - scenarios: { - smoke: { - executor: 'constant-vus', - vus: 3, - duration: "1s", - }, - }, +export const localOptions: Options = { thresholds: { - 'http_req_duration{group:::Issuer creates credential offer}': ['max >= 0'], - 'http_reqs{group:::Issuer creates credential offer}': ['count >= 0'], - 'group_duration{group:::Issuer creates credential offer}': ['max >= 0'], - }, -}; - + 'group_duration{group:::Issuer creates credential offer}': ['avg < 15000'] + } +} +export let options: Options = merge(localOptions, defaultOptions) export const issuer = new Issuer(); export const holder = new Holder(); @@ -52,22 +31,29 @@ export function setup() { holder.finalizeConnectionWithIssuer(); }); - return { + group("Issuer creates credential schema", function () { + issuer.createCredentialSchema(); + }); + + return { issuerDid: issuer.did, holderDid: holder.did, + issuerSchema: issuer.schema, connectionWithHolder: issuer.connectionWithHolder!, connectionWithIssuer: holder.connectionWithIssuer! }; } -export default (data: { issuerDid: string; holderDid: string; connectionWithHolder: Connection, connectionWithIssuer: Connection }) => { +export default (data: { issuerDid: string; holderDid: string; issuerSchema: CredentialSchemaResponse, connectionWithHolder: Connection, connectionWithIssuer: Connection }) => { // This is the only way to pass data from setup to default issuer.did = data.issuerDid; + issuer.schema = data.issuerSchema holder.did = data.holderDid; issuer.connectionWithHolder = data.connectionWithHolder; holder.connectionWithIssuer = data.connectionWithIssuer; + group('Issuer creates credential offer', function () { issuer.createCredentialOffer(); }); diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-schema-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-schema-test.ts index 095eee806f..9cdaca922c 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-schema-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/credentials/credential-schema-test.ts @@ -1,43 +1,33 @@ -import { group } from 'k6'; -import { Options } from 'k6/options'; -import { Issuer } from '../../actors'; +import { group } from "k6"; +import { Options } from "k6/options"; +import { Issuer } from "../../actors"; +import { defaultOptions } from "../../scenarios/default"; +import merge from "ts-deepmerge"; -export let options: Options = { - scenarios: { - smoke: { - executor: 'constant-vus', - vus: 3, - duration: "1s", - }, - }, +export const localOptions: Options = { thresholds: { - 'http_req_duration{group:::Issuer creates credential schema}': ['max >= 0'], - 'http_reqs{group:::Issuer creates credential schema}': ['count >= 0'], - 'group_duration{group:::Issuer creates credential schema}': ['max >= 0'], - checks: ['rate==1'], - http_req_duration: ['p(95)<=100'], - }, -}; - + 'group_duration{group:::Issuer creates credential schema}': ['avg < 15000'] + } +} +export let options: Options = merge(localOptions, defaultOptions) export const issuer = new Issuer(); export function setup() { - group('Issuer publishes DID', function () { + group("Issuer publishes DID", function () { issuer.createUnpublishedDid(); issuer.publishDid(); }); - return { + return { issuerDid: issuer.did, }; } -export default (data: { issuerDid: string; }) => { - +export default (data: { issuerDid: string }) => { // This is the only way to pass data from setup to default issuer.did = data.issuerDid; - group('Issuer creates credential schema', function () { + group("Issuer creates credential schema", function () { issuer.createCredentialSchema(); }); }; diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/create-prism-did-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/create-prism-did-test.ts index dfd9350ca4..601d44331c 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/create-prism-did-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/create-prism-did-test.ts @@ -1,26 +1,20 @@ import { Options } from 'k6/options'; import { Issuer } from '../../actors'; +import { defaultOptions } from "../../scenarios/default"; +import { group } from "k6"; +import merge from "ts-deepmerge"; -export let options: Options = { - scenarios: { - smoke: { - executor: 'constant-vus', - vus: 3, - duration: "1m", - }, - }, +export const localOptions: Options = { thresholds: { - http_req_failed: [{ - threshold: 'rate==0', - abortOnFail: true, - }], - http_req_duration: ['p(95)<=500'], - checks: ['rate==1'], - }, -}; + 'group_duration{group:::Issuer create unpublished DID}': ['avg < 15000'] + } +} +export let options: Options = merge(localOptions, defaultOptions) const issuer = new Issuer(); export default () => { + group("Issuer create unpublished DID", function () { issuer.createUnpublishedDid(); + }); }; diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/did-publishing-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/did-publishing-test.ts index 0fd5eb4644..0e58083e39 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/did-publishing-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/dids/did-publishing-test.ts @@ -1,23 +1,21 @@ -import { Options } from 'k6/options'; -import { Issuer } from '../../actors'; +import { Options } from "k6/options"; +import { Issuer } from "../../actors"; +import merge from "ts-deepmerge"; +import { group } from "k6"; +import { defaultOptions } from "../../scenarios/default"; -export let options: Options = { - stages: [ - { duration: '1m', target: 5 }, - ], - thresholds: { - http_req_failed: [{ - threshold: 'rate<=0.05', - abortOnFail: true, - }], - http_req_duration: ['p(95)<=100'], - checks: ['rate>=0.99'], - }, - }; +export const localOptions: Options = { + thresholds: { + "group_duration{group:::Issuer create published DID}": ["avg < 15000"], + }, +}; +export let options: Options = merge(localOptions, defaultOptions); const issuer = new Issuer(); export default () => { + group("Issuer create published DID", function () { issuer.createUnpublishedDid(); issuer.publishDid(); + }); }; diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/connection-flow-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/connection-flow-test.ts index 563a36bf11..af3338219b 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/connection-flow-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/connection-flow-test.ts @@ -1,24 +1,25 @@ -import { Options } from 'k6/options'; -import { connectionFlow } from '../common'; - -export let options: Options = { - scenarios: { - smoke: { - executor: 'constant-vus', - vus: 3, - duration: "1m", - }, - }, +import { Options } from "k6/options"; +import { connectionFlow } from "../common"; +import { defaultOptions } from "../../scenarios/default"; +import merge from "ts-deepmerge"; +export const localOptions: Options = { thresholds: { - http_req_failed: [{ - threshold: 'rate==0', - abortOnFail: true, - }], - http_req_duration: ['p(95)<=500'], - checks: ['rate==1'], + "group_duration{group:::Issuer initiates connection with Holder}": [ + "avg < 15000", + ], + "group_duration{group:::Holder accepts connection with Issuer}": [ + "avg < 15000", + ], + "group_duration{group:::Issuer finalizes connection with Holder}": [ + "avg < 15000", + ], + "group_duration{group:::Holder finalizes connection with Issuer}": [ + "avg < 15000", + ], }, }; +export let options: Options = merge(localOptions, defaultOptions); -export default() => { +export default () => { connectionFlow(); -} +}; diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/full-flow-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/full-flow-test.ts deleted file mode 100644 index fe17b7148e..0000000000 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/full-flow-test.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { group } from 'k6'; -import { Options } from 'k6/options'; -import { Issuer, Holder, Verifier } from '../../actors'; - -export let options: Options = { - vus: 1, - iterations: 1 -}; - -const issuer = new Issuer(); -const holder = new Holder(); -const verifier = new Verifier(); - -export function setup() { - group('Issuer publishes DID', function () { - issuer.createUnpublishedDid(); - issuer.publishDid(); - }); - - group('Holder creates unpublished DID', function () { - holder.createUnpublishedDid(); - }); - - return { issuerDid: issuer.did, holderDid: holder.did }; -} - -export default (data: { issuerDid: string; holderDid: string; }) => { - - issuer.did = data.issuerDid; - holder.did = data.holderDid; - - group('Holder connects with Issuer', function () { - issuer.createHolderConnection(); - holder.acceptIssuerConnection(issuer.connectionWithHolder!.invitation); - issuer.finalizeConnectionWithHolder(); - holder.finalizeConnectionWithIssuer(); - }); - - group('Issuer creates credential offer for Holder', function () { - issuer.createCredentialOffer(); - issuer.waitForCredentialOfferToBeSent(); - holder.waitAndAcceptCredentialOffer(); - issuer.receiveCredentialRequest(); - issuer.issueCredential(); - issuer.waitForCredentialToBeSent(); - holder.receiveCredential(); - }); - - group('Holder connects with Verifier', function () { - verifier.createHolderConnection(); - holder.acceptVerifierConnection(verifier.connectionWithHolder!.invitation); - verifier.finalizeConnectionWithHolder(); - holder.finalizeConnectionWithVerifier(); - }); - - group('Verifier requests proof from Holder', function () { - verifier.requestProof(); - holder.waitAndAcceptProofRequest(); - verifier.acknowledgeProof(); - }); - -}; diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/issuance-flow-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/issuance-flow-test.ts index c4f52a0094..8904341126 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/issuance-flow-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/issuance-flow-test.ts @@ -1,76 +1,84 @@ -import { group } from 'k6'; -import { Options } from 'k6/options'; -import {issuer, holder} from '../common'; -import { CredentialSchemaResponse } from '@input-output-hk/prism-typescript-client'; +import { group } from "k6"; +import { Options } from "k6/options"; +import { issuer, holder } from "../common"; +import { CredentialSchemaResponse } from "@input-output-hk/prism-typescript-client"; +import { defaultOptions } from "../../scenarios/default"; +import merge from "ts-deepmerge"; -export let options: Options = { - scenarios: { - smoke: { - executor: 'constant-vus', - vus: 5, - duration: "3m", - }, - }, +export const localOptions: Options = { thresholds: { - http_req_failed: [{ - threshold: 'rate==0', - abortOnFail: true, - }], - http_req_duration: ['p(95)<=500'], - checks: ['rate==1'], + "group_duration{group:::Issuer connects with Holder}": ["avg < 15000"], + "group_duration{group:::Issuer creates credential offer for Holder}": [ + "avg < 60000", + ], + "group_duration{group:::Issuer issues credential to Holder}": [ + "avg < 60000", + ], + "group_duration{group:::Holder receives credential from Issuer}": [ + "avg < 15000", + ], }, }; +export let options: Options = merge(localOptions, defaultOptions); // This is setup code. It runs once at the beginning of the test, regardless of the number of VUs. export function setup() { - - group('Issuer publishes DID', function () { + group("Issuer publishes DID", function () { issuer.createUnpublishedDid(); issuer.publishDid(); }); - group('Issuer creates credential schema', function () { + group("Issuer creates credential schema", function () { issuer.createCredentialSchema(); }); - group('Holder creates unpublished DID', function () { + group("Holder creates unpublished DID", function () { holder.createUnpublishedDid(); }); - return { issuerDid: issuer.did, holderDid: holder.did, issuerSchema: issuer.schema }; + return { + issuerDid: issuer.did, + holderDid: holder.did, + issuerSchema: issuer.schema, + }; } -export default (data: { issuerDid: string; holderDid: string; issuerSchema: CredentialSchemaResponse}) => { - +export default (data: { + issuerDid: string; + holderDid: string; + issuerSchema: CredentialSchemaResponse; +}) => { // This is the only way to pass data from setup to default issuer.did = data.issuerDid; issuer.schema = data.issuerSchema; holder.did = data.holderDid; - group('Issuer connects with Holder', function () { + group("Issuer connects with Holder", function () { issuer.createHolderConnection(); holder.acceptIssuerConnection(issuer.connectionWithHolder!.invitation); issuer.finalizeConnectionWithHolder(); holder.finalizeConnectionWithIssuer(); }); - group('Issuer creates credential offer for Holder', function () { + group("Issuer creates credential offer for Holder", function () { issuer.createCredentialOffer(); issuer.waitForCredentialOfferToBeSent(); }); - - group('Holder achieves and accepts credential offer from Issuer', function () { - holder.waitAndAcceptCredentialOffer(issuer.credential!.thid); - }); - group('Issuer issues credential to Holder', function () { + group( + "Holder achieves and accepts credential offer from Issuer", + function () { + holder.waitAndAcceptCredentialOffer(issuer.credential!.thid); + } + ); + + group("Issuer issues credential to Holder", function () { issuer.receiveCredentialRequest(); issuer.issueCredential(); issuer.waitForCredentialToBeSent(); }); - group('Holder receives credential from Issuer', function () { + group("Holder receives credential from Issuer", function () { holder.receiveCredential(); }); - }; diff --git a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/present-proof-flow-test.ts b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/present-proof-flow-test.ts index 667c0d4c90..a333fbd5f3 100644 --- a/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/present-proof-flow-test.ts +++ b/tests/performance-tests/atala-performance-tests-k6/src/tests/flows/present-proof-flow-test.ts @@ -1,61 +1,66 @@ -import { group } from 'k6'; -import { Options } from 'k6/options'; -import { Issuer, Holder, Verifier } from '../../actors'; -import { CredentialSchemaResponse } from '@input-output-hk/prism-typescript-client'; +import { group } from "k6"; +import { Options } from "k6/options"; +import { Issuer, Holder, Verifier } from "../../actors"; +import { CredentialSchemaResponse } from "@input-output-hk/prism-typescript-client"; +import { defaultOptions } from "../../scenarios/default"; +import merge from "ts-deepmerge"; -export let options: Options = { - scenarios: { - smoke: { - executor: 'constant-vus', - vus: 5, - duration: "3m", - }, - }, +export const localOptions: Options = { thresholds: { - http_req_failed: [{ - threshold: 'rate==0', - abortOnFail: true, - }], - http_req_duration: ['p(95)<=500'], - checks: ['rate==1'], + "group_duration{group:::Holder connects with Issuer}": ["avg < 15000"], + "group_duration{group:::Issuer creates credential offer for Holder}": [ + "avg < 120000", + ], + "group_duration{group:::Holder connects with Verifier}": ["avg < 15000"], + "group_duration{group:::Verifier requests proof from Holder}": [ + "avg < 15000", + ], }, }; +export let options: Options = merge(localOptions, defaultOptions); const issuer = new Issuer(); const holder = new Holder(); const verifier = new Verifier(); export function setup() { - group('Issuer publishes DID', function () { + group("Issuer publishes DID", function () { issuer.createUnpublishedDid(); issuer.publishDid(); }); - group('Issuer creates credential schema', function () { + group("Issuer creates credential schema", function () { issuer.createCredentialSchema(); }); - group('Holder creates unpublished DID', function () { + group("Holder creates unpublished DID", function () { holder.createUnpublishedDid(); }); - return { issuerDid: issuer.did, holderDid: holder.did, issuerSchema: issuer.schema }; + return { + issuerDid: issuer.did, + holderDid: holder.did, + issuerSchema: issuer.schema, + }; } -export default (data: { issuerDid: string; holderDid: string; issuerSchema: CredentialSchemaResponse; }) => { - +export default (data: { + issuerDid: string; + holderDid: string; + issuerSchema: CredentialSchemaResponse; +}) => { issuer.did = data.issuerDid; issuer.schema = data.issuerSchema; holder.did = data.holderDid; - group('Holder connects with Issuer', function () { + group("Holder connects with Issuer", function () { issuer.createHolderConnection(); holder.acceptIssuerConnection(issuer.connectionWithHolder!.invitation); issuer.finalizeConnectionWithHolder(); holder.finalizeConnectionWithIssuer(); }); - group('Issuer creates credential offer for Holder', function () { + group("Issuer creates credential offer for Holder", function () { issuer.createCredentialOffer(); issuer.waitForCredentialOfferToBeSent(); holder.waitAndAcceptCredentialOffer(issuer.credential!.thid); @@ -65,17 +70,16 @@ export default (data: { issuerDid: string; holderDid: string; issuerSchema: Cred holder.receiveCredential(); }); - group('Holder connects with Verifier', function () { + group("Holder connects with Verifier", function () { verifier.createHolderConnection(); holder.acceptVerifierConnection(verifier.connectionWithHolder!.invitation); verifier.finalizeConnectionWithHolder(); holder.finalizeConnectionWithVerifier(); }); - group('Verifier requests proof from Holder', function () { + group("Verifier requests proof from Holder", function () { verifier.requestProof(); holder.waitAndAcceptProofRequest(verifier.presentation!.thid); verifier.acknowledgeProof(); }); - }; diff --git a/tests/performance-tests/atala-performance-tests-k6/yarn.lock b/tests/performance-tests/atala-performance-tests-k6/yarn.lock index 81ef0af7bf..2568095e62 100644 --- a/tests/performance-tests/atala-performance-tests-k6/yarn.lock +++ b/tests/performance-tests/atala-performance-tests-k6/yarn.lock @@ -2388,6 +2388,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +ts-deepmerge@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ts-deepmerge/-/ts-deepmerge-6.2.0.tgz#77554381a4884d66cab799470bc2620a1c9d84e8" + integrity sha512-2qxI/FZVDPbzh63GwWIZYE7daWKtwXZYuyc8YNq0iTmMUwn4mL0jRLsp6hfFlgbdRSR4x2ppe+E86FnvEpN7Nw== + typescript@5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"