diff options
Diffstat (limited to 'packages/taler-harness/src/harness/harness.ts')
-rw-r--r-- | packages/taler-harness/src/harness/harness.ts | 117 |
1 files changed, 113 insertions, 4 deletions
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index 134709541..83c8f60d1 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -21,8 +21,6 @@ * @author Florian Dold <dold@taler.net> */ -const logger = new Logger("harness.ts"); - /** * Imports */ @@ -43,6 +41,7 @@ import { parsePaytoUri, stringToBytes, TalerProtocolDuration, + WalletNotification, } from "@gnu-taler/taler-util"; import { BankAccessApi, @@ -57,9 +56,9 @@ import { import { deepStrictEqual } from "assert"; import axiosImp, { AxiosError } from "axios"; import { ChildProcess, spawn } from "child_process"; -import * as child_process from "child_process"; import * as fs from "fs"; import * as http from "http"; +import * as net from "node:net"; import * as path from "path"; import * as readline from "readline"; import { URL } from "url"; @@ -76,6 +75,15 @@ import { TipCreateRequest, TippingReserveStatus, } from "./merchantApiTypes.js"; +import { + createRemoteWallet, + getClientFromRemoteWallet, + makeNotificationWaiter, + RemoteWallet, + WalletNotificationWaiter, +} from "@gnu-taler/taler-wallet-core/remote"; + +const logger = new Logger("harness.ts"); const axios = axiosImp.default; @@ -1831,7 +1839,7 @@ export async function runTestWithState( const handleSignal = (s: string) => { logger.warn( - `**** received fatal process event, terminating test ${testName}`, + `**** received fatal process event (${s}), terminating test ${testName}`, ); gc.shutdownSync(); process.exit(1); @@ -1885,6 +1893,107 @@ export interface WalletCliOpts { cryptoWorkerType?: "sync" | "node-worker-thread"; } +function tryUnixConnect(socketPath: string): Promise<void> { + return new Promise((resolve, reject) => { + const client = net.createConnection(socketPath); + client.on("error", (e) => { + reject(e); + }); + client.on("connect", () => { + client.end(); + resolve(); + }); + }); +} + +export class WalletService { + walletProc: ProcessWrapper | undefined; + + constructor(private globalState: GlobalTestState, private name: string) {} + + get socketPath() { + const unixPath = path.join(this.globalState.testDir, `${this.name}.sock`); + return unixPath; + } + + async start(): Promise<void> { + const dbPath = path.join( + this.globalState.testDir, + `walletdb-${this.name}.json`, + ); + const unixPath = this.socketPath; + this.globalState.spawnService( + "taler-wallet-cli", + [ + "--wallet-db", + dbPath, + "advanced", + "serve", + "--unix-path", + unixPath, + ], + `wallet-${this.name}`, + ); + } + + async pingUntilAvailable(): Promise<void> { + while (1) { + try { + await tryUnixConnect(this.socketPath); + } catch (e) { + logger.info(`connection attempt failed: ${e}`); + await delayMs(200); + continue; + } + logger.info("connection to wallet-core succeeded"); + break; + } + } +} + +export interface WalletClientArgs { + unixPath: string; + onNotification?(n: WalletNotification): void; +} + +export class WalletClient { + remoteWallet: RemoteWallet | undefined = undefined; + waiter: WalletNotificationWaiter = makeNotificationWaiter(); + + constructor(private args: WalletClientArgs) {} + + async connect(): Promise<void> { + const waiter = this.waiter; + const walletClient = this; + const w = await createRemoteWallet({ + socketFilename: this.args.unixPath, + notificationHandler(n) { + if (walletClient.args.onNotification) { + walletClient.args.onNotification(n); + } + waiter.notify(n); + console.log("got notification from wallet-core in WalletClient"); + }, + }); + this.remoteWallet = w; + + this.waiter.waitForNotificationCond; + } + + get client() { + if (!this.remoteWallet) { + throw Error("wallet not connected"); + } + return getClientFromRemoteWallet(this.remoteWallet); + } + + waitForNotificationCond( + cond: (n: WalletNotification) => boolean, + ): Promise<void> { + return this.waiter.waitForNotificationCond(cond); + } +} + export class WalletCli { private currentTimetravel: Duration | undefined; private _client: WalletCoreApiClient; |