Skip to content

Commit

Permalink
Add test users for load test
Browse files Browse the repository at this point in the history
  • Loading branch information
grausof committed Oct 2, 2024
1 parent a88facc commit 3d800cf
Show file tree
Hide file tree
Showing 11 changed files with 4,149 additions and 7 deletions.
3 changes: 2 additions & 1 deletion apps/io-wallet-user-func/local.settings.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"PidIssuerApiRootCACertificate": "PID_ISSUER_API_ROOT_CA_CERTIFICATE",
"PidIssuerHealthCheckEnabled": "PID_ISSUER_HEALTH_CHECK_ENABLED",
"PidIssuerApiRequestTimeout": "PID_ISSUER_API_REQUEST_TIMEOUT",
"HttpRequestTimeout": "HTTP_REQUEST_TIMEOUT"
"HttpRequestTimeout": "HTTP_REQUEST_TIMEOUT",
"TestUsersFiscalCodeForLoadTest": "FISCAL_CODE_OF_TEST_USERS_SEPARATED_BY_COMMA"
}
}
33 changes: 32 additions & 1 deletion apps/io-wallet-user-func/src/app/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { parse } from "@pagopa/handler-kit";
import { NumberFromString } from "@pagopa/ts-commons/lib/numbers";
import { readableReportSimplified } from "@pagopa/ts-commons/lib/reporters";
import { NonEmptyString } from "@pagopa/ts-commons/lib/strings";
import { FiscalCode, NonEmptyString } from "@pagopa/ts-commons/lib/strings";
import { sequenceS } from "fp-ts/lib/Apply";
import * as RE from "fp-ts/lib/ReaderEither";
import { flow, pipe } from "fp-ts/lib/function";
Expand Down Expand Up @@ -117,12 +117,19 @@ export type PidIssuerApiClientConfig = t.TypeOf<
typeof PidIssuerApiClientConfig
>;

const LoadTestConfig = t.type({
testUsersFiscalCode: t.array(FiscalCode),
});

export type LoadTestConfig = t.TypeOf<typeof LoadTestConfig>;

export const Config = t.type({
attestationService: AttestationServiceConfiguration,
azure: AzureConfig,
crypto: CryptoConfiguration,
federationEntity: FederationEntityMetadata,
jwtValidator: JwtValidatorConfig,
loadTest: LoadTestConfig,
pdvTokenizer: PdvTokenizerApiClientConfig,
pidIssuer: PidIssuerApiClientConfig,
trialSystem: TrialSystemApiClientConfig,
Expand Down Expand Up @@ -322,6 +329,29 @@ const getTrialSystemConfigFromEnvironment: RE.ReaderEither<
),
);

const getLoadTestConfigFromEnvironment: RE.ReaderEither<
NodeJS.ProcessEnv,
Error,
LoadTestConfig
> = pipe(
sequenceS(RE.Apply)({
testUsersFiscalCode: pipe(
readFromEnvironment("TestUsersFiscalCodeForLoadTest"),
RE.map((testUsers) => testUsers.split(",")),
RE.chainW(
flow(
t.array(FiscalCode).decode,
RE.fromEither,
RE.mapLeft((errs) => Error(readableReportSimplified(errs))),
),
),
),
}),
RE.map(({ testUsersFiscalCode }) => ({
testUsersFiscalCode,
})),
);

const getPidIssuerConfigFromEnvironment: RE.ReaderEither<
NodeJS.ProcessEnv,
Error,
Expand Down Expand Up @@ -391,6 +421,7 @@ export const getConfigFromEnvironment: RE.ReaderEither<
RE.map(({ timeout }) => timeout),
),
jwtValidator: getJwtValidatorConfigFromEnvironment,
loadTest: getLoadTestConfigFromEnvironment,
pdvTokenizer: getPdvTokenizerConfigFromEnvironment,
pidIssuer: getPidIssuerConfigFromEnvironment,
trialSystem: getTrialSystemConfigFromEnvironment,
Expand Down
8 changes: 8 additions & 0 deletions apps/io-wallet-user-func/src/app/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { GetUserByFiscalCodeFunction } from "@/infra/azure/functions/get-user-by
import { HealthFunction } from "@/infra/azure/functions/health";
import { SetWalletInstanceStatusFunction } from "@/infra/azure/functions/set-wallet-instance-status";
import { CryptoSigner } from "@/infra/crypto/signer";
import { IoLoadTestClient } from "@/infra/io-load-test/client";
import { jwtValidate } from "@/infra/jwt-validator";
import { PidIssuerClient } from "@/infra/pid-issuer/client";
import { TrialSystemClient } from "@/infra/trial-system/client";
Expand Down Expand Up @@ -62,6 +63,11 @@ const pidIssuerClient = new PidIssuerClient(
config.federationEntity.basePath.href,
);

const ioLoadTestClient = new IoLoadTestClient(
config.loadTest,
pdvTokenizerClient,
);

app.http("healthCheck", {
authLevel: "anonymous",
handler: HealthFunction({
Expand All @@ -79,6 +85,7 @@ app.http("createWalletAttestation", {
handler: CreateWalletAttestationFunction({
attestationServiceConfiguration: config.attestationService,
federationEntityMetadata: config.federationEntity,
loadTestClient: ioLoadTestClient,
nonceRepository,
signer,
walletInstanceRepository,
Expand All @@ -91,6 +98,7 @@ app.http("createWalletInstance", {
authLevel: "function",
handler: CreateWalletInstanceFunction({
attestationServiceConfiguration: config.attestationService,
loadTestClient: ioLoadTestClient,
nonceRepository,
walletInstanceRepository,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
GOOGLE_PUBLIC_KEY,
} from "@/app/config";
import { iOSMockData } from "@/infra/attestation-service/ios/__test__/config";
import { LoadTestClient } from "@/load-test";
import { NonceRepository } from "@/nonce";
import { WalletInstanceRepository } from "@/wallet-instance";
import { GRANT_TYPE_KEY_ATTESTATION } from "@/wallet-provider";
Expand All @@ -16,6 +17,7 @@ import { decode } from "cbor-x";
import * as E from "fp-ts/Either";
import * as O from "fp-ts/Option";
import * as TE from "fp-ts/TaskEither";
import { User } from "io-wallet-common/user";
import * as jose from "jose";
import { describe, expect, it } from "vitest";

Expand Down Expand Up @@ -75,6 +77,13 @@ const walletInstanceRepository: WalletInstanceRepository = {
const data = Buffer.from(assertion, "base64");
const { authenticatorData, signature } = decode(data);

const loadTestClient: LoadTestClient = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isTestUser: function (user: User): E.Either<Error, boolean> {
return E.right(false);
},
};

describe("CreateWalletAttestationHandler", async () => {
const josePrivateKey = await jose.importJWK(privateEcKey);
const walletAttestationRequest = await new jose.SignJWT({
Expand Down Expand Up @@ -114,6 +123,7 @@ describe("CreateWalletAttestationHandler", async () => {
federationEntityMetadata,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
signer,
Expand Down Expand Up @@ -164,6 +174,7 @@ describe("CreateWalletAttestationHandler", async () => {
federationEntityMetadata,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
signer,
Expand Down Expand Up @@ -216,6 +227,7 @@ describe("CreateWalletAttestationHandler", async () => {
federationEntityMetadata,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
signer,
Expand Down Expand Up @@ -262,6 +274,7 @@ describe("CreateWalletAttestationHandler", async () => {
federationEntityMetadata,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
signer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import {
decodeBase64String,
} from "@/app/config";
import { iOSMockData } from "@/infra/attestation-service/ios/__test__/config";
import { LoadTestClient } from "@/load-test";
import { NonceRepository } from "@/nonce";
import { WalletInstanceRepository } from "@/wallet-instance";
import * as H from "@pagopa/handler-kit";
import * as L from "@pagopa/logger";
import * as O from "fp-ts/Option";
import * as TE from "fp-ts/TaskEither";
import * as E from "fp-ts/lib/Either";
import { User } from "io-wallet-common/user";
import { describe, expect, it } from "vitest";

import { CreateWalletInstanceHandler } from "../create-wallet-instance";
Expand All @@ -31,6 +34,13 @@ describe("CreateWalletInstanceHandler", () => {
insert: () => TE.left(new Error("not implemented")),
};

const loadTestClient: LoadTestClient = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isTestUser: function (user: User): E.Either<Error, boolean> {
return E.right(false);
},
};

const walletInstanceRepository: WalletInstanceRepository = {
batchPatch: () => TE.right(undefined),
get: () => TE.left(new Error("not implemented")),
Expand Down Expand Up @@ -76,6 +86,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository,
Expand All @@ -99,6 +110,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository,
Expand Down Expand Up @@ -128,6 +140,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository,
Expand Down Expand Up @@ -159,6 +172,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository,
Expand Down Expand Up @@ -192,6 +206,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository: nonceRepositoryThatFailsOnDelete,
walletInstanceRepository,
Expand Down Expand Up @@ -229,6 +244,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository: walletInstanceRepositoryThatFailsOnInsert,
Expand Down Expand Up @@ -266,6 +282,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository:
Expand Down Expand Up @@ -304,6 +321,7 @@ describe("CreateWalletInstanceHandler", () => {
attestationServiceConfiguration,
input: req,
inputDecoder: H.HttpRequest,
loadTestClient,
logger,
nonceRepository,
walletInstanceRepository: walletInstanceRepositoryThatFailsOnBatchPatch,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { validateAssertion } from "@/attestation-service";
import { isTestUser, validateTestAssertion } from "@/load-test";
import { createWalletAttestation } from "@/wallet-attestation";
import { verifyWalletAttestationRequest } from "@/wallet-attestation-request";
import { getValidWalletInstance } from "@/wallet-instance";
Expand Down Expand Up @@ -61,10 +62,17 @@ export const CreateWalletAttestationHandler = H.of((req: H.HttpRequest) =>
),
),
RTE.chainW((walletInstance) =>
validateAssertion(
walletAttestationRequest,
walletInstance.hardwareKey,
walletInstance.signCount,
pipe(
isTestUser(user),
RTE.chainW((isTest) =>
isTest
? validateTestAssertion()
: validateAssertion(
walletAttestationRequest,
walletInstance.hardwareKey,
walletInstance.signCount,
),
),
),
),
RTE.chainW(() => createWalletAttestation(walletAttestationRequest)),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { validateAttestation } from "@/attestation-service";
import { isTestUser, validateTestAttestation } from "@/load-test";
import {
insertWalletInstance,
revokeUserValidWalletInstancesExceptOne,
Expand Down Expand Up @@ -51,7 +52,12 @@ export const CreateWalletInstanceHandler = H.of((req: H.HttpRequest) =>
RTE.chainW(({ user, walletInstanceRequest }) =>
pipe(
consumeNonce(walletInstanceRequest.challenge),
RTE.chainW(() => validateAttestation(walletInstanceRequest)),
RTE.chainW(() => isTestUser(user)),
RTE.chainW((isTest) =>
isTest
? validateTestAttestation(walletInstanceRequest, user)
: validateAttestation(walletInstanceRequest),
),
RTE.bind("walletInstance", ({ deviceDetails, hardwareKey }) =>
RTE.right({
createdAt: new Date(),
Expand Down
40 changes: 40 additions & 0 deletions apps/io-wallet-user-func/src/infra/io-load-test/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { LoadTestConfig } from "@/app/config";
import { LoadTestClient } from "@/load-test";
import * as E from "fp-ts/lib/Either";
import * as O from "fp-ts/lib/Option";
import * as RA from "fp-ts/lib/ReadonlyArray";
import { pipe } from "fp-ts/lib/function";
import { PdvTokenizerClient } from "io-wallet-common/infra/pdv-tokenizer/client";
import { User } from "io-wallet-common/user";

export class IoLoadTestClient implements LoadTestClient {
#users: string[];

isTestUser = (user: User) =>
pipe(
this.#users,
RA.findFirst((userId) => userId === user.id),
O.isSome,
E.right,
);

//Since it is necessary to have the list of users already processed at startup in the constructor, a functional approach is not used.
constructor(
{ testUsersFiscalCode }: LoadTestConfig,
pdvTokenizerClient: PdvTokenizerClient,
) {
const users: string[] = [];
testUsersFiscalCode.forEach((fiscalCode) =>
pdvTokenizerClient
.getOrCreateUserByFiscalCode(fiscalCode)()
.then((result) => {
if (result._tag === "Right") {
const fiscalCodesTokens = result.right;
users.push(fiscalCodesTokens.id);
}
}),
);

this.#users = users;
}
}
Loading

0 comments on commit 3d800cf

Please sign in to comment.