From b9e4ec7274b84fa80cd31fba64ba9f216407877c Mon Sep 17 00:00:00 2001 From: Benoit Devos Date: Fri, 16 Feb 2024 16:04:24 +0100 Subject: [PATCH] feat: test legal officer workload. logion-network/logion-internal#1136 --- packages/client-node/integration/Main.spec.ts | 2 +- packages/client/src/Types.ts | 8 ++ packages/client/test/Types.spec.ts | 106 ++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 packages/client/test/Types.spec.ts diff --git a/packages/client-node/integration/Main.spec.ts b/packages/client-node/integration/Main.spec.ts index 0c082e0f..a56b2129 100644 --- a/packages/client-node/integration/Main.spec.ts +++ b/packages/client-node/integration/Main.spec.ts @@ -36,7 +36,7 @@ describe("Logion SDK", () => { }); it("fetches workload", async () => { - await workload(state, ALICE, BOB, ALICE); + await workload(state, ALICE, BOB); }); it("estimates fees", async () => { diff --git a/packages/client/src/Types.ts b/packages/client/src/Types.ts index 140c7db4..7dded640 100644 --- a/packages/client/src/Types.ts +++ b/packages/client/src/Types.ts @@ -76,6 +76,10 @@ class Workload { } + flushCache() { + this.workloads = {}; + } + private async fetchAndStoreWorkload(legalOfficer: LegalOfficerClass) { if (!legalOfficer.token) { throw new Error("Authenticate first"); @@ -164,4 +168,8 @@ export class LegalOfficerClass implements LegalOfficer { async getWorkload(): Promise { return LegalOfficerClass.workload.getWorkload(this); } + + static flushWorkloadCache() { + LegalOfficerClass.workload.flushCache(); + } } diff --git a/packages/client/test/Types.spec.ts b/packages/client/test/Types.spec.ts new file mode 100644 index 00000000..8c89a84d --- /dev/null +++ b/packages/client/test/Types.spec.ts @@ -0,0 +1,106 @@ +import { ALICE, BOB } from "./Utils.js"; +import { LegalOfficer, LegalOfficerClass, AxiosFactory } from "../src/index.js"; +import { Mock, It, Times } from "moq.ts"; +import { AxiosInstance, AxiosResponse } from "axios"; + +describe("Workload", () => { + + const aliceToken = "alice-token"; + const bobToken = "bob-token"; + + beforeEach(() => { + LegalOfficerClass.flushWorkloadCache(); + }) + + function setupAxios(legalOfficer: LegalOfficer, token: string, workload: number): + { axiosFactory: Mock, axiosInstance: Mock } { + + const axiosFactory = new Mock(); + const axiosInstance = new Mock(); + const workloads: Record = {}; + workloads[legalOfficer.address] = workload; + axiosInstance.setup(instance => instance.put( + `/api/workload`, + It.Is<{ legalOfficerAddresses: string[] }>(params => params.legalOfficerAddresses.includes(legalOfficer.address))) + ) + .returns(Promise.resolve({ data: { workloads } } as AxiosResponse)); + axiosFactory.setup(instance => instance.buildAxiosInstance(legalOfficer.node, token)) + .returns(axiosInstance.object()); + return { axiosFactory, axiosInstance } + } + + it("fetches once when called twice in a row", async () => { + + const { axiosFactory, axiosInstance } = setupAxios(ALICE, aliceToken, 42); + const alice = new LegalOfficerClass({ + legalOfficer: ALICE, + token: aliceToken, + axiosFactory: axiosFactory.object() + }); + + expect(await alice.getWorkload()).toEqual(42); + expect(await alice.getWorkload()).toEqual(42); + + axiosInstance.verify(instance => instance.put(`/api/workload`, It.IsAny()), Times.Once()) + }) + + it("fetches twice for LLOs on DISTINCT nodes", async () => { + + const aliceAxios = setupAxios(ALICE, aliceToken, 42); + const alice = new LegalOfficerClass({ + legalOfficer: ALICE, + token: aliceToken, + axiosFactory: aliceAxios.axiosFactory.object() + }); + expect(await alice.getWorkload()).toEqual(42); + aliceAxios.axiosInstance.verify(instance => instance.put(`/api/workload`, It.IsAny()), Times.Once()) + + const bobAxios = setupAxios(BOB, bobToken, 24); + const bob = new LegalOfficerClass({ + legalOfficer: BOB, + token: bobToken, + axiosFactory: bobAxios.axiosFactory.object() + }); + expect(await bob.getWorkload()).toEqual(24); + bobAxios.axiosInstance.verify(instance => instance.put(`/api/workload`, It.IsAny()), Times.Once()) + }) + + it("fetches once for LLOs on SAME node", async () => { + + const sameNode = ALICE.node; + const axiosFactory = new Mock(); + const axiosInstance = new Mock(); + const workloads: Record = {}; + workloads[ALICE.address] = 42; + workloads[BOB.address] = 24; + axiosInstance.setup(instance => instance.put( + `/api/workload`, + It.Is<{ legalOfficerAddresses: string[] }>(params => params.legalOfficerAddresses.includes(ALICE.address) && params.legalOfficerAddresses.includes(BOB.address))) + ) + .returns(Promise.resolve({ data: { workloads } } as AxiosResponse)); + axiosFactory.setup(instance => instance.buildAxiosInstance(sameNode, aliceToken)) + .returns(axiosInstance.object()); + axiosFactory.setup(instance => instance.buildAxiosInstance(sameNode, bobToken)) + .returns(axiosInstance.object()); + + const alice = new LegalOfficerClass({ + legalOfficer: { + ...ALICE, + node: sameNode + }, + token: aliceToken, + axiosFactory: axiosFactory.object() + }); + const bob = new LegalOfficerClass({ + legalOfficer: { + ...BOB, + node: sameNode + }, + token: bobToken, + axiosFactory: axiosFactory.object() + }); + expect(await alice.getWorkload()).toEqual(42); + expect(await bob.getWorkload()).toEqual(24); + axiosInstance.verify(instance => instance.put(`/api/workload`, It.IsAny()), Times.Once()) + }) +})