diff options
22 files changed, 229 insertions, 99 deletions
diff --git a/packages/taler-harness/package.json b/packages/taler-harness/package.json index 3af8b73e3..eee369f66 100644 --- a/packages/taler-harness/package.json +++ b/packages/taler-harness/package.json @@ -16,7 +16,7 @@ }, "type": "module", "scripts": { - "compile": "./build.mjs", + "compile": "tsc && ./build.mjs", "check": "tsc", "test": "tsc", "clean": "rimraf lib dist tsconfig.tsbuildinfo", diff --git a/packages/taler-harness/src/bench1.ts b/packages/taler-harness/src/bench1.ts index 941d9244a..fb7cc9e1f 100644 --- a/packages/taler-harness/src/bench1.ts +++ b/packages/taler-harness/src/bench1.ts @@ -48,6 +48,7 @@ export async function runBench1(configJson: any): Promise<void> { const myHttpLib = createPlatformHttpLib({ enableThrottling: false, + allowHttp: true, }); const numIter = b1conf.iterations ?? 1; @@ -92,8 +93,8 @@ export async function runBench1(configJson: any): Promise<void> { }, features: { batchWithdrawal, - } - } + }, + }, }); wallet = res.wallet; getDbStats = res.getDbStats; diff --git a/packages/taler-harness/src/bench2.ts b/packages/taler-harness/src/bench2.ts index ff87da52a..48ac76b9f 100644 --- a/packages/taler-harness/src/bench2.ts +++ b/packages/taler-harness/src/bench2.ts @@ -34,6 +34,7 @@ import { findDenomOrThrow, refreshCoin, SynchronousCryptoWorkerFactoryPlain, + Wallet, withdrawCoin, } from "@gnu-taler/taler-wallet-core"; @@ -56,6 +57,7 @@ export async function runBench2(configJson: any): Promise<void> { const http = createPlatformHttpLib({ enableThrottling: false, + allowHttp: true, }); const numIter = benchConf.iterations ?? 1; @@ -84,7 +86,9 @@ export async function runBench2(configJson: any): Promise<void> { console.log("reserve found"); - const d1 = findDenomOrThrow(exchangeInfo, `${curr}:8`); + const d1 = findDenomOrThrow(exchangeInfo, `${curr}:8`, { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }); for (let j = 0; j < numDeposits; j++) { console.log("withdrawing coin"); @@ -111,8 +115,12 @@ export async function runBench2(configJson: any): Promise<void> { }); const refreshDenoms = [ - findDenomOrThrow(exchangeInfo, `${curr}:1`), - findDenomOrThrow(exchangeInfo, `${curr}:1`), + findDenomOrThrow(exchangeInfo, `${curr}:1`, { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }), + findDenomOrThrow(exchangeInfo, `${curr}:1`, { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }), ]; console.log("refreshing coin"); diff --git a/packages/taler-harness/src/bench3.ts b/packages/taler-harness/src/bench3.ts index 2573aec14..ffafc75d2 100644 --- a/packages/taler-harness/src/bench3.ts +++ b/packages/taler-harness/src/bench3.ts @@ -52,6 +52,7 @@ export async function runBench3(configJson: any): Promise<void> { const myHttpLib = createPlatformHttpLib({ enableThrottling: false, + allowHttp: true, }); const numIter = b3conf.iterations ?? 1; @@ -96,7 +97,7 @@ export async function runBench3(configJson: any): Promise<void> { httpLib: myHttpLib, config: { features: { - batchWithdrawal: batchWithdrawal, + batchWithdrawal, }, testing: { insecureTrustExchange: trustExchange, diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts index b6e80cfb7..0ee0d7960 100644 --- a/packages/taler-harness/src/harness/harness.ts +++ b/packages/taler-harness/src/harness/harness.ts @@ -102,6 +102,21 @@ interface WaitResult { signal: NodeJS.Signals | null; } +class CommandError extends Error { + constructor( + public message: string, + public logName: string, + public command: string, + public args: string[], + public env: Env, + public code: number | null, + ) { + super(message); + } +} +interface Env { + [index: string]: string | undefined; +} /** * Run a shell command, return stdout. */ @@ -109,15 +124,15 @@ export async function sh( t: GlobalTestState, logName: string, command: string, - env: { [index: string]: string | undefined } = process.env, + env: Env = process.env, ): Promise<string> { - logger.info(`running command ${command}`); + logger.trace(`running command ${command}`); return new Promise((resolve, reject) => { const stdoutChunks: Buffer[] = []; const proc = spawn(command, { stdio: ["inherit", "pipe", "pipe"], shell: true, - env: env, + env, }); proc.stdout.on("data", (x) => { if (x instanceof Buffer) { @@ -132,16 +147,34 @@ export async function sh( }); proc.stderr.pipe(stderrLog); proc.on("exit", (code, signal) => { - logger.info(`child process exited (${code} / ${signal})`); + logger.info(`child process ${logName} exited (${code} / ${signal})`); if (code != 0) { - reject(Error(`Unexpected exit code ${code} for '${command}'`)); + reject( + new CommandError( + `Unexpected exit code ${code}`, + logName, + command, + [], + env, + code, + ), + ); return; } const b = Buffer.concat(stdoutChunks).toString("utf-8"); resolve(b); }); - proc.on("error", () => { - reject(Error("Child process had error")); + proc.on("error", (err) => { + reject( + new CommandError( + "Child process had error:" + err.message, + logName, + command, + [], + env, + null, + ), + ); }); }); } @@ -170,6 +203,7 @@ export async function runCommand( env: { [index: string]: string | undefined } = process.env, ): Promise<string> { logger.info(`running command ${shellescape([command, ...args])}`); + return new Promise((resolve, reject) => { const stdoutChunks: Buffer[] = []; const proc = spawn(command, args, { @@ -190,16 +224,34 @@ export async function runCommand( }); proc.stderr.pipe(stderrLog); proc.on("exit", (code, signal) => { - logger.info(`child process exited (${code} / ${signal})`); + logger.trace(`child process exited (${code} / ${signal})`); if (code != 0) { - reject(Error(`Unexpected exit code ${code} for '${command}'`)); + reject( + new CommandError( + `Unexpected exit code ${code}`, + logName, + command, + [], + env, + code, + ), + ); return; } const b = Buffer.concat(stdoutChunks).toString("utf-8"); resolve(b); }); - proc.on("error", () => { - reject(Error("Child process had error")); + proc.on("error", (err) => { + reject( + new CommandError( + "Child process had error:" + err.message, + logName, + command, + [], + env, + null, + ), + ); }); }); } @@ -321,14 +373,14 @@ export class GlobalTestState { logName: string, env: { [index: string]: string | undefined } = process.env, ): ProcessWrapper { - logger.info( + logger.trace( `spawning process (${logName}): ${shellescape([command, ...args])}`, ); const proc = spawn(command, args, { stdio: ["inherit", "pipe", "pipe"], env: env, }); - logger.info(`spawned process (${logName}) with pid ${proc.pid}`); + logger.trace(`spawned process (${logName}) with pid ${proc.pid}`); proc.on("error", (err) => { logger.warn(`could not start process (${command})`, err); }); @@ -355,18 +407,18 @@ export class GlobalTestState { return; } if (shouldLingerInTest()) { - logger.info("refusing to shut down, lingering was requested"); + logger.trace("refusing to shut down, lingering was requested"); return; } this.inShutdown = true; - logger.info("shutting down"); + logger.trace("shutting down"); for (const s of this.servers) { s.close(); s.removeAllListeners(); } for (const p of this.procs) { if (p.proc.exitCode == null) { - logger.info(`killing process ${p.proc.pid}`); + logger.trace(`killing process ${p.proc.pid}`); p.proc.kill("SIGTERM"); await p.wait(); } @@ -473,12 +525,12 @@ export async function pingProc( } while (true) { try { - logger.info(`pinging ${serviceName} at ${url}`); + logger.trace(`pinging ${serviceName} at ${url}`); const resp = await axios.get(url); - logger.info(`service ${serviceName} available`); + logger.trace(`service ${serviceName} available`); return; } catch (e: any) { - logger.info(`service ${serviceName} not ready:`, e.toString()); + logger.warn(`service ${serviceName} not ready:`, e.toString()); //console.log(e); await delayMs(1000); } @@ -506,7 +558,10 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle { sandboxProc: ProcessWrapper | undefined; nexusProc: ProcessWrapper | undefined; - http = createPlatformHttpLib(); + http = createPlatformHttpLib({ + allowHttp: true, + enableThrottling: false, + }); static async create( gc: GlobalTestState, @@ -539,12 +594,6 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle { return url.href; } - // FIXME: Duplicate? Where is this needed? - get baseUrlAccessApi(): string { - let url = new URL("access-api/", this.baseUrlDemobank); - return url.href; - } - get bankAccessApiBaseUrl(): string { let url = new URL("access-api/", this.baseUrlDemobank); return url.href; @@ -555,7 +604,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle { } get baseUrl(): string { - return this.baseUrlAccessApi; + return this.bankAccessApiBaseUrl; } async setSuggestedExchange( @@ -587,7 +636,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle { await this.start(); await this.pingUntilAvailable(); await LibeufinSandboxApi.createDemobankAccount(accountName, password, { - baseUrl: this.baseUrlAccessApi, + baseUrl: this.bankAccessApiBaseUrl, }); let bankAccountLabel = accountName; await LibeufinSandboxApi.createDemobankEbicsSubscriber( @@ -697,7 +746,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle { let accountInfoResp = await LibeufinSandboxApi.demobankAccountInfo( "admin", "secret", - { baseUrl: this.baseUrlAccessApi }, + { baseUrl: this.bankAccessApiBaseUrl }, accountName, // bank account label. ); return { @@ -793,7 +842,7 @@ export class FakebankService { proc: ProcessWrapper | undefined; - http = createPlatformHttpLib(); + http = createPlatformHttpLib({ allowHttp: true, enableThrottling: false }); // We store "created" accounts during setup and // register them after startup. @@ -1282,7 +1331,9 @@ export class ExchangeService implements ExchangeServiceInterface { } } - logger.info("configuring bank accounts", accounts); + const accountsDescription = accounts.map((acc) => ` * ${acc}`).join("\n"); + logger.info("configuring bank accounts:"); + logger.info(accountsDescription); for (const acc of accounts) { await runCommand( @@ -1494,7 +1545,7 @@ export class MerchantApiClient { ) {} // FIXME: Migrate everything to this in favor of axios - http = createPlatformHttpLib(); + http = createPlatformHttpLib({ allowHttp: true, enableThrottling: false }); async changeAuth(auth: MerchantAuthConfiguration): Promise<void> { const url = new URL("private/auth", this.baseUrl); @@ -2052,6 +2103,7 @@ export async function runTestWithState( try { logger.info("running test in directory", gc.testDir); await Promise.race([testMain(gc), p.promise]); + logger.info("completed test in directory", gc.testDir); status = "pass"; if (linger) { const rl = readline.createInterface({ @@ -2068,9 +2120,22 @@ export async function runTestWithState( rl.close(); } } catch (e) { - console.error("FATAL: test failed with exception", e); - if (e instanceof TalerError) { - console.error(`error detail: ${j2s(e.errorDetail)}`); + if (e instanceof CommandError) { + console.error("FATAL: test failed for", e.logName); + const errorLog = fs.readFileSync( + path.join(gc.testDir, `${e.logName}-stderr.log`), + ); + console.error(`${e.message}: "${e.command}"`); + console.error(errorLog.toString()); + console.error(e); + } else if (e instanceof TalerError) { + console.error( + "FATAL: test failed", + e.message, + `error detail: ${j2s(e.errorDetail)}`, + ); + } else { + console.error("FATAL: test failed with exception", e); } status = "fail"; } finally { @@ -2243,23 +2308,28 @@ export class WalletCli { const cryptoWorkerArg = cliOpts.cryptoWorkerType ? `--crypto-worker=${cliOpts.cryptoWorkerType}` : ""; - const resp = await sh( - self.globalTestState, - `wallet-${self.name}`, - `taler-wallet-cli ${ - self.timetravelArg ?? "" - } ${cryptoWorkerArg} --no-throttle -LTRACE --skip-defaults --wallet-db '${ - self.dbfile - }' api '${op}' ${shellWrap(JSON.stringify(payload))}`, - ); + const logName = `wallet-${self.name}`; + const command = `taler-wallet-cli ${ + self.timetravelArg ?? "" + } ${cryptoWorkerArg} --allow-http --no-throttle -LTRACE --skip-defaults --wallet-db '${ + self.dbfile + }' api '${op}' ${shellWrap(JSON.stringify(payload))}`; + const resp = await sh(self.globalTestState, logName, command); logger.info("--- wallet core response ---"); logger.info(resp); logger.info("--- end of response ---"); - let ar: any; + let ar: CoreApiResponse; try { - ar = JSON.parse(resp) as CoreApiResponse; + ar = JSON.parse(resp); } catch (e) { - throw new Error("wallet CLI did not return a proper JSON response"); + throw new CommandError( + "wallet CLI did not return a proper JSON response", + logName, + command, + [], + {}, + null, + ); } if (ar.type === "error") { throw TalerError.fromUncheckedDetail(ar.error); @@ -2295,6 +2365,7 @@ export class WalletCli { `wallet-${this.name}`, "taler-wallet-cli", [ + "--allow-http", "--no-throttle", ...this.timetravelArgArr, "-LTRACE", @@ -2313,6 +2384,7 @@ export class WalletCli { `wallet-${this.name}`, "taler-wallet-cli", [ + "--allow-http", "--no-throttle", "--skip-defaults", "-LTRACE", diff --git a/packages/taler-harness/src/harness/helpers.ts b/packages/taler-harness/src/harness/helpers.ts index 516312ed8..b13fa9cf4 100644 --- a/packages/taler-harness/src/harness/helpers.ts +++ b/packages/taler-harness/src/harness/helpers.ts @@ -99,7 +99,7 @@ export interface EnvOptions { /** * Run a test case with a simple TESTKUDOS Taler environment, consisting * of one exchange, one bank and one merchant. - * + * * @deprecated use {@link createSimpleTestkudosEnvironmentV2} instead */ export async function createSimpleTestkudosEnvironment( @@ -557,7 +557,7 @@ export async function withdrawViaBankV2( /** * Withdraw balance. - * + * * @deprecated use {@link withdrawViaBankV2 instead} */ export async function withdrawViaBank( diff --git a/packages/taler-harness/src/harness/libeufin-apis.ts b/packages/taler-harness/src/harness/libeufin-apis.ts index 4ef588fb5..cb9acdaa4 100644 --- a/packages/taler-harness/src/harness/libeufin-apis.ts +++ b/packages/taler-harness/src/harness/libeufin-apis.ts @@ -5,10 +5,9 @@ * the services get actually started and managed. */ +import { URL } from "@gnu-taler/taler-util"; import axiosImp from "axios"; const axios = axiosImp.default; -import { AmountString, Logger, URL } from "@gnu-taler/taler-util"; -import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; export interface LibeufinSandboxServiceInterface { baseUrl: string; diff --git a/packages/taler-harness/src/harness/libeufin.ts b/packages/taler-harness/src/harness/libeufin.ts index 001fb613b..8fd276fad 100644 --- a/packages/taler-harness/src/harness/libeufin.ts +++ b/packages/taler-harness/src/harness/libeufin.ts @@ -899,6 +899,8 @@ export function findNexusPayment( ): LibeufinNexusMoneyMovement | void { let transactions = payments["transactions"]; for (let i = 0; i < transactions.length; i++) { + //FIXME: last line won't compile with the current definition of the type + //@ts-ignore let batches = transactions[i]["camtData"]["batches"]; for (let y = 0; y < batches.length; y++) { let movements = batches[y]["batchTransactions"]; diff --git a/packages/taler-harness/src/index.ts b/packages/taler-harness/src/index.ts index 30b557986..bd58a7fd6 100644 --- a/packages/taler-harness/src/index.ts +++ b/packages/taler-harness/src/index.ts @@ -17,10 +17,6 @@ /** * Imports. */ -import { deepStrictEqual } from "assert"; -import fs from "fs"; -import os from "os"; -import path from "path"; import { addPaytoQueryParams, Amounts, @@ -28,33 +24,34 @@ import { decodeCrock, j2s, Logger, - parsePaytoUri, rsaBlind, setGlobalLogLevelFromString, } from "@gnu-taler/taler-util"; +import { clk } from "@gnu-taler/taler-util/clk"; +import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; +import { + BankAccessApiClient, + CryptoDispatcher, + downloadExchangeInfo, + SynchronousCryptoWorkerFactoryPlain, + topupReserveWithDemobank, +} from "@gnu-taler/taler-wallet-core"; +import { deepStrictEqual } from "assert"; +import fs from "fs"; +import os from "os"; +import path from "path"; import { runBench1 } from "./bench1.js"; import { runBench2 } from "./bench2.js"; import { runBench3 } from "./bench3.js"; +import { runEnvFull } from "./env-full.js"; import { runEnv1 } from "./env1.js"; import { GlobalTestState, MerchantApiClient, - MerchantPrivateApi, runTestWithState, } from "./harness/harness.js"; import { getTestInfo, runTests } from "./integrationtests/testrunner.js"; import { lintExchangeDeployment } from "./lint.js"; -import { runEnvFull } from "./env-full.js"; -import { clk } from "@gnu-taler/taler-util/clk"; -import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; -import { - BankAccessApiClient, - checkReserve, - CryptoDispatcher, - downloadExchangeInfo, - SynchronousCryptoWorkerFactoryPlain, - topupReserveWithDemobank, -} from "@gnu-taler/taler-wallet-core"; const logger = new Logger("taler-harness:index.ts"); @@ -213,6 +210,7 @@ deploymentCli baseUrl: args.tipTopup.bankAccessUrl, username: args.tipTopup.bankAccount, password: args.tipTopup.bankPassword, + allowHttp: true, }); const paytoUri = addPaytoQueryParams(tipReserveResp.payto_uri, { @@ -495,6 +493,12 @@ testingCli .flag("experimental", ["--experimental"], { help: "Include tests marked as experimental", }) + .flag("failFast", ["--fail-fast"], { + help: "Exit after the first error", + }) + .flag("waitOnFail", ["--wait-on-fail"], { + help: "Exit after the first error", + }) .flag("quiet", ["--quiet"], { help: "Produce less output.", }) @@ -504,6 +508,8 @@ testingCli .action(async (args) => { await runTests({ includePattern: args.runIntegrationtests.pattern, + failFast: args.runIntegrationtests.failFast, + waitOnFail: args.runIntegrationtests.waitOnFail, suiteSpec: args.runIntegrationtests.suites, dryRun: args.runIntegrationtests.dryRun, verbosity: args.runIntegrationtests.quiet ? 0 : 1, diff --git a/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts b/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts index 561a10e6d..38cbd6925 100644 --- a/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts +++ b/packages/taler-harness/src/integrationtests/test-age-restrictions-merchant.ts @@ -166,6 +166,7 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) { wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, accountName: exchangeBankAccount.accountName, accountPassword: exchangeBankAccount.accountPassword, + allowHttp: true, }); await wireGatewayApiClient.adminAddIncoming({ diff --git a/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts b/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts index d129a5217..0bb811f39 100644 --- a/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts +++ b/packages/taler-harness/src/integrationtests/test-age-restrictions-peer.ts @@ -18,9 +18,7 @@ * Imports. */ import { AbsoluteTime, Duration } from "@gnu-taler/taler-util"; -import { - WalletApiOperation, -} from "@gnu-taler/taler-wallet-core"; +import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { defaultCoinConfig } from "../harness/denomStructures.js"; import { GlobalTestState, WalletCli } from "../harness/harness.js"; import { diff --git a/packages/taler-harness/src/integrationtests/test-bank-api.ts b/packages/taler-harness/src/integrationtests/test-bank-api.ts index d97860a2c..5e3448625 100644 --- a/packages/taler-harness/src/integrationtests/test-bank-api.ts +++ b/packages/taler-harness/src/integrationtests/test-bank-api.ts @@ -126,6 +126,7 @@ export async function runBankApiTest(t: GlobalTestState) { wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, accountName: exchangeBankAccount.accountName, accountPassword: exchangeBankAccount.accountPassword, + allowHttp: true, }); await wireGatewayApiClient.adminAddIncoming({ diff --git a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts index 18a3c172a..6c0d070d0 100644 --- a/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts +++ b/packages/taler-harness/src/integrationtests/test-exchange-deposit.ts @@ -33,6 +33,7 @@ import { refreshCoin, SynchronousCryptoWorkerFactoryPlain, topupReserveWithDemobank, + Wallet, withdrawCoin, } from "@gnu-taler/taler-wallet-core"; import { GlobalTestState } from "../harness/harness.js"; @@ -46,7 +47,10 @@ export async function runExchangeDepositTest(t: GlobalTestState) { const { bank, exchange } = await createSimpleTestkudosEnvironment(t); - const http = createPlatformHttpLib(); + const http = createPlatformHttpLib({ + allowHttp: true, + enableThrottling: false, + }); const cryptiDisp = new CryptoDispatcher( new SynchronousCryptoWorkerFactoryPlain(), ); @@ -71,7 +75,9 @@ export async function runExchangeDepositTest(t: GlobalTestState) { await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub); - const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8"); + const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8", { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }); const coin = await withdrawCoin({ http, diff --git a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts index 20285cb6a..7f94628a6 100644 --- a/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts +++ b/packages/taler-harness/src/integrationtests/test-exchange-timetravel.ts @@ -24,7 +24,10 @@ import { Duration, durationFromSpec, } from "@gnu-taler/taler-util"; -import { createPlatformHttpLib, readSuccessResponseJsonOrThrow } from "@gnu-taler/taler-util/http"; +import { + createPlatformHttpLib, + readSuccessResponseJsonOrThrow, +} from "@gnu-taler/taler-util/http"; import { makeNoFeeCoinConfig } from "../harness/denomStructures.js"; import { BankService, @@ -65,7 +68,10 @@ async function applyTimeTravel( } } -const http = createPlatformHttpLib(); +const http = createPlatformHttpLib({ + allowHttp: true, + enableThrottling: false, +}); /** * Basic time travel test. diff --git a/packages/taler-harness/src/integrationtests/test-kyc.ts b/packages/taler-harness/src/integrationtests/test-kyc.ts index b7ea0ff77..b86c8dd5b 100644 --- a/packages/taler-harness/src/integrationtests/test-kyc.ts +++ b/packages/taler-harness/src/integrationtests/test-kyc.ts @@ -340,7 +340,10 @@ export async function runKycTest(t: GlobalTestState) { // We now simulate the user interacting with the KYC service, // which would usually done in the browser. - const httpLib = createPlatformHttpLib(); + const httpLib = createPlatformHttpLib({ + allowHttp: true, + enableThrottling: false, + }); const kycServerResp = await httpLib.get(kycNotif.kycUrl); const kycLoginResp = await kycServerResp.json(); console.log("kyc server resp:", j2s(kycLoginResp)); diff --git a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts index 2fafe7584..975ba707b 100644 --- a/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts +++ b/packages/taler-harness/src/integrationtests/test-merchant-spec-public-orders.ts @@ -39,7 +39,10 @@ import { withdrawViaBank, } from "../harness/helpers.js"; -const httpLib = createPlatformHttpLib(); +const httpLib = createPlatformHttpLib({ + allowHttp: true, + enableThrottling: false, +}); interface Context { merchant: MerchantService; diff --git a/packages/taler-harness/src/integrationtests/test-tipping.ts b/packages/taler-harness/src/integrationtests/test-tipping.ts index 69afad6fd..b124fbf0d 100644 --- a/packages/taler-harness/src/integrationtests/test-tipping.ts +++ b/packages/taler-harness/src/integrationtests/test-tipping.ts @@ -61,6 +61,7 @@ export async function runTippingTest(t: GlobalTestState) { wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, accountName: exchangeBankAccount.accountName, accountPassword: exchangeBankAccount.accountPassword, + allowHttp: true, }); await wireGatewayApiClient.adminAddIncoming({ diff --git a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts index 37be9dcf8..c384a6e74 100644 --- a/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts +++ b/packages/taler-harness/src/integrationtests/test-wallet-dbless.ts @@ -33,6 +33,7 @@ import { refreshCoin, SynchronousCryptoWorkerFactoryPlain, topupReserveWithDemobank, + Wallet, withdrawCoin, } from "@gnu-taler/taler-wallet-core"; import { GlobalTestState } from "../harness/harness.js"; @@ -46,7 +47,10 @@ export async function runWalletDblessTest(t: GlobalTestState) { const { bank, exchange } = await createSimpleTestkudosEnvironment(t); - const http = createPlatformHttpLib(); + const http = createPlatformHttpLib({ + allowHttp: true, + enableThrottling: false, + }); const cryptiDisp = new CryptoDispatcher( new SynchronousCryptoWorkerFactoryPlain(), ); @@ -84,7 +88,9 @@ export async function runWalletDblessTest(t: GlobalTestState) { await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub); - const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8"); + const d1 = findDenomOrThrow(exchangeInfo, "TESTKUDOS:8", { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }); const coin = await withdrawCoin({ http, @@ -125,8 +131,12 @@ export async function runWalletDblessTest(t: GlobalTestState) { }); const refreshDenoms = [ - findDenomOrThrow(exchangeInfo, "TESTKUDOS:1"), - findDenomOrThrow(exchangeInfo, "TESTKUDOS:1"), + findDenomOrThrow(exchangeInfo, "TESTKUDOS:1", { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }), + findDenomOrThrow(exchangeInfo, "TESTKUDOS:1", { + denomselAllowLate: Wallet.defaultConfig.testing.denomselAllowLate, + }), ]; await refreshCoin({ diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts index 4a79d2c21..a356a5c1a 100644 --- a/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts +++ b/packages/taler-harness/src/integrationtests/test-withdrawal-manual.ts @@ -73,6 +73,7 @@ export async function runWithdrawalManualTest(t: GlobalTestState) { wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, accountName: exchangeBankAccount.accountName, accountPassword: exchangeBankAccount.accountPassword, + allowHttp: true, }); await wireGatewayApiClient.adminAddIncoming({ diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts b/packages/taler-harness/src/integrationtests/testrunner.ts index f845f4e99..c76ce1b18 100644 --- a/packages/taler-harness/src/integrationtests/testrunner.ts +++ b/packages/taler-harness/src/integrationtests/testrunner.ts @@ -14,7 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { CancellationToken, minimatch } from "@gnu-taler/taler-util"; +import { CancellationToken, Logger, minimatch } from "@gnu-taler/taler-util"; import * as child_process from "child_process"; import * as fs from "fs"; import * as os from "os"; @@ -105,6 +105,7 @@ import { runExchangeDepositTest } from "./test-exchange-deposit.js"; /** * Test runner. */ +const logger = new Logger("testrunner.ts"); /** * Spec for one test. @@ -199,6 +200,8 @@ export interface TestRunSpec { includePattern?: string; suiteSpec?: string; dryRun?: boolean; + failFast?: boolean; + waitOnFail?: boolean; includeExperimental: boolean; noTimeout: boolean; verbosity: number; @@ -357,7 +360,7 @@ export async function runTests(spec: TestRunSpec) { if (token.isCancelled) { return; } - console.log(`process exited code=${code} signal=${signal}`); + logger.info(`process exited code=${code} signal=${signal}`); if (signal) { reject(new Error(`test worker exited with signal ${signal}`)); } else if (code != 0) { @@ -385,6 +388,10 @@ export async function runTests(spec: TestRunSpec) { try { result = await token.racePromise(resultPromise); + if (result.status === "fail" && spec.failFast) { + logger.error("test failed and failing fast, exit!"); + throw Error("exit on fail fast"); + } } catch (e: any) { console.error(`test ${testName} timed out`); if (token.isCancelled) { @@ -469,10 +476,9 @@ if (runTestInstrStr && process.argv.includes("__TWCLI_TESTWORKER")) { const { testRootDir, testName } = JSON.parse( runTestInstrStr, ) as RunTestChildInstruction; - console.log(`running test ${testName} in worker process`); process.on("disconnect", () => { - console.log("got disconnect from parent"); + logger.trace("got disconnect from parent"); process.exit(3); }); @@ -486,35 +492,36 @@ if (runTestInstrStr && process.argv.includes("__TWCLI_TESTWORKER")) { } if (!process.send) { - console.error("can't communicate with parent"); + logger.error("can't communicate with parent"); process.exit(2); } if (!testMain) { - console.log(`test ${testName} not found`); + logger.info(`test ${testName} not found`); process.exit(2); } const testDir = path.join(testRootDir, testName); - console.log(`running test ${testName}`); + logger.info(`running test ${testName}`); const gc = new GlobalTestState({ testDir, }); const testResult = await runTestWithState(gc, testMain, testName); + logger.info(`done test ${testName}: ${testResult.status}`); process.send(testResult); }; runTest() .then(() => { - console.log(`test ${testName} finished in worker`); + logger.trace(`test ${testName} finished in worker`); if (shouldLingerInTest()) { - console.log("lingering ..."); + logger.trace("lingering ..."); return; } process.exit(0); }) .catch((e) => { - console.log(e); + logger.error(e); process.exit(1); }); } diff --git a/packages/taler-harness/src/lint.ts b/packages/taler-harness/src/lint.ts index 3d3805e79..715227c7f 100644 --- a/packages/taler-harness/src/lint.ts +++ b/packages/taler-harness/src/lint.ts @@ -53,7 +53,10 @@ interface PubkeyConf { masterPublicKey: string; } -const httpLib = createPlatformHttpLib(); +const httpLib = createPlatformHttpLib({ + enableThrottling: false, + allowHttp: true, +}); interface ShellResult { stdout: string; diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts index 7f78be23a..ab9f43004 100644 --- a/packages/taler-wallet-core/src/wallet.ts +++ b/packages/taler-wallet-core/src/wallet.ts @@ -1604,6 +1604,7 @@ export class Wallet { allowHttp: false, }, testing: { + preventThrottling: false, devModeActive: false, insecureTrustExchange: false, denomselAllowLate: false, |