improved log, added allow-http flag and prevent thrott

This commit is contained in:
Sebastian 2023-04-24 13:13:20 -03:00
parent 4889ae9c9b
commit b3cdd3409e
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
22 changed files with 231 additions and 101 deletions

View File

@ -16,7 +16,7 @@
}, },
"type": "module", "type": "module",
"scripts": { "scripts": {
"compile": "./build.mjs", "compile": "tsc && ./build.mjs",
"check": "tsc", "check": "tsc",
"test": "tsc", "test": "tsc",
"clean": "rimraf lib dist tsconfig.tsbuildinfo", "clean": "rimraf lib dist tsconfig.tsbuildinfo",

View File

@ -48,6 +48,7 @@ export async function runBench1(configJson: any): Promise<void> {
const myHttpLib = createPlatformHttpLib({ const myHttpLib = createPlatformHttpLib({
enableThrottling: false, enableThrottling: false,
allowHttp: true,
}); });
const numIter = b1conf.iterations ?? 1; const numIter = b1conf.iterations ?? 1;
@ -92,8 +93,8 @@ export async function runBench1(configJson: any): Promise<void> {
}, },
features: { features: {
batchWithdrawal, batchWithdrawal,
} },
} },
}); });
wallet = res.wallet; wallet = res.wallet;
getDbStats = res.getDbStats; getDbStats = res.getDbStats;

View File

@ -34,6 +34,7 @@ import {
findDenomOrThrow, findDenomOrThrow,
refreshCoin, refreshCoin,
SynchronousCryptoWorkerFactoryPlain, SynchronousCryptoWorkerFactoryPlain,
Wallet,
withdrawCoin, withdrawCoin,
} from "@gnu-taler/taler-wallet-core"; } from "@gnu-taler/taler-wallet-core";
@ -56,6 +57,7 @@ export async function runBench2(configJson: any): Promise<void> {
const http = createPlatformHttpLib({ const http = createPlatformHttpLib({
enableThrottling: false, enableThrottling: false,
allowHttp: true,
}); });
const numIter = benchConf.iterations ?? 1; const numIter = benchConf.iterations ?? 1;
@ -84,7 +86,9 @@ export async function runBench2(configJson: any): Promise<void> {
console.log("reserve found"); 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++) { for (let j = 0; j < numDeposits; j++) {
console.log("withdrawing coin"); console.log("withdrawing coin");
@ -111,8 +115,12 @@ export async function runBench2(configJson: any): Promise<void> {
}); });
const refreshDenoms = [ 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"); console.log("refreshing coin");

View File

@ -52,6 +52,7 @@ export async function runBench3(configJson: any): Promise<void> {
const myHttpLib = createPlatformHttpLib({ const myHttpLib = createPlatformHttpLib({
enableThrottling: false, enableThrottling: false,
allowHttp: true,
}); });
const numIter = b3conf.iterations ?? 1; const numIter = b3conf.iterations ?? 1;
@ -96,7 +97,7 @@ export async function runBench3(configJson: any): Promise<void> {
httpLib: myHttpLib, httpLib: myHttpLib,
config: { config: {
features: { features: {
batchWithdrawal: batchWithdrawal, batchWithdrawal,
}, },
testing: { testing: {
insecureTrustExchange: trustExchange, insecureTrustExchange: trustExchange,

View File

@ -102,6 +102,21 @@ interface WaitResult {
signal: NodeJS.Signals | null; 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. * Run a shell command, return stdout.
*/ */
@ -109,15 +124,15 @@ export async function sh(
t: GlobalTestState, t: GlobalTestState,
logName: string, logName: string,
command: string, command: string,
env: { [index: string]: string | undefined } = process.env, env: Env = process.env,
): Promise<string> { ): Promise<string> {
logger.info(`running command ${command}`); logger.trace(`running command ${command}`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const stdoutChunks: Buffer[] = []; const stdoutChunks: Buffer[] = [];
const proc = spawn(command, { const proc = spawn(command, {
stdio: ["inherit", "pipe", "pipe"], stdio: ["inherit", "pipe", "pipe"],
shell: true, shell: true,
env: env, env,
}); });
proc.stdout.on("data", (x) => { proc.stdout.on("data", (x) => {
if (x instanceof Buffer) { if (x instanceof Buffer) {
@ -132,16 +147,34 @@ export async function sh(
}); });
proc.stderr.pipe(stderrLog); proc.stderr.pipe(stderrLog);
proc.on("exit", (code, signal) => { proc.on("exit", (code, signal) => {
logger.info(`child process exited (${code} / ${signal})`); logger.info(`child process ${logName} exited (${code} / ${signal})`);
if (code != 0) { if (code != 0) {
reject(Error(`Unexpected exit code ${code} for '${command}'`)); reject(
new CommandError(
`Unexpected exit code ${code}`,
logName,
command,
[],
env,
code,
),
);
return; return;
} }
const b = Buffer.concat(stdoutChunks).toString("utf-8"); const b = Buffer.concat(stdoutChunks).toString("utf-8");
resolve(b); resolve(b);
}); });
proc.on("error", () => { proc.on("error", (err) => {
reject(Error("Child process had error")); 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, env: { [index: string]: string | undefined } = process.env,
): Promise<string> { ): Promise<string> {
logger.info(`running command ${shellescape([command, ...args])}`); logger.info(`running command ${shellescape([command, ...args])}`);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const stdoutChunks: Buffer[] = []; const stdoutChunks: Buffer[] = [];
const proc = spawn(command, args, { const proc = spawn(command, args, {
@ -190,16 +224,34 @@ export async function runCommand(
}); });
proc.stderr.pipe(stderrLog); proc.stderr.pipe(stderrLog);
proc.on("exit", (code, signal) => { proc.on("exit", (code, signal) => {
logger.info(`child process exited (${code} / ${signal})`); logger.trace(`child process exited (${code} / ${signal})`);
if (code != 0) { if (code != 0) {
reject(Error(`Unexpected exit code ${code} for '${command}'`)); reject(
new CommandError(
`Unexpected exit code ${code}`,
logName,
command,
[],
env,
code,
),
);
return; return;
} }
const b = Buffer.concat(stdoutChunks).toString("utf-8"); const b = Buffer.concat(stdoutChunks).toString("utf-8");
resolve(b); resolve(b);
}); });
proc.on("error", () => { proc.on("error", (err) => {
reject(Error("Child process had error")); reject(
new CommandError(
"Child process had error:" + err.message,
logName,
command,
[],
env,
null,
),
);
}); });
}); });
} }
@ -321,14 +373,14 @@ export class GlobalTestState {
logName: string, logName: string,
env: { [index: string]: string | undefined } = process.env, env: { [index: string]: string | undefined } = process.env,
): ProcessWrapper { ): ProcessWrapper {
logger.info( logger.trace(
`spawning process (${logName}): ${shellescape([command, ...args])}`, `spawning process (${logName}): ${shellescape([command, ...args])}`,
); );
const proc = spawn(command, args, { const proc = spawn(command, args, {
stdio: ["inherit", "pipe", "pipe"], stdio: ["inherit", "pipe", "pipe"],
env: env, env: env,
}); });
logger.info(`spawned process (${logName}) with pid ${proc.pid}`); logger.trace(`spawned process (${logName}) with pid ${proc.pid}`);
proc.on("error", (err) => { proc.on("error", (err) => {
logger.warn(`could not start process (${command})`, err); logger.warn(`could not start process (${command})`, err);
}); });
@ -355,18 +407,18 @@ export class GlobalTestState {
return; return;
} }
if (shouldLingerInTest()) { if (shouldLingerInTest()) {
logger.info("refusing to shut down, lingering was requested"); logger.trace("refusing to shut down, lingering was requested");
return; return;
} }
this.inShutdown = true; this.inShutdown = true;
logger.info("shutting down"); logger.trace("shutting down");
for (const s of this.servers) { for (const s of this.servers) {
s.close(); s.close();
s.removeAllListeners(); s.removeAllListeners();
} }
for (const p of this.procs) { for (const p of this.procs) {
if (p.proc.exitCode == null) { if (p.proc.exitCode == null) {
logger.info(`killing process ${p.proc.pid}`); logger.trace(`killing process ${p.proc.pid}`);
p.proc.kill("SIGTERM"); p.proc.kill("SIGTERM");
await p.wait(); await p.wait();
} }
@ -473,12 +525,12 @@ export async function pingProc(
} }
while (true) { while (true) {
try { try {
logger.info(`pinging ${serviceName} at ${url}`); logger.trace(`pinging ${serviceName} at ${url}`);
const resp = await axios.get(url); const resp = await axios.get(url);
logger.info(`service ${serviceName} available`); logger.trace(`service ${serviceName} available`);
return; return;
} catch (e: any) { } catch (e: any) {
logger.info(`service ${serviceName} not ready:`, e.toString()); logger.warn(`service ${serviceName} not ready:`, e.toString());
//console.log(e); //console.log(e);
await delayMs(1000); await delayMs(1000);
} }
@ -506,7 +558,10 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
sandboxProc: ProcessWrapper | undefined; sandboxProc: ProcessWrapper | undefined;
nexusProc: ProcessWrapper | undefined; nexusProc: ProcessWrapper | undefined;
http = createPlatformHttpLib(); http = createPlatformHttpLib({
allowHttp: true,
enableThrottling: false,
});
static async create( static async create(
gc: GlobalTestState, gc: GlobalTestState,
@ -539,12 +594,6 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
return url.href; 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 { get bankAccessApiBaseUrl(): string {
let url = new URL("access-api/", this.baseUrlDemobank); let url = new URL("access-api/", this.baseUrlDemobank);
return url.href; return url.href;
@ -555,7 +604,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
} }
get baseUrl(): string { get baseUrl(): string {
return this.baseUrlAccessApi; return this.bankAccessApiBaseUrl;
} }
async setSuggestedExchange( async setSuggestedExchange(
@ -587,7 +636,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
await this.start(); await this.start();
await this.pingUntilAvailable(); await this.pingUntilAvailable();
await LibeufinSandboxApi.createDemobankAccount(accountName, password, { await LibeufinSandboxApi.createDemobankAccount(accountName, password, {
baseUrl: this.baseUrlAccessApi, baseUrl: this.bankAccessApiBaseUrl,
}); });
let bankAccountLabel = accountName; let bankAccountLabel = accountName;
await LibeufinSandboxApi.createDemobankEbicsSubscriber( await LibeufinSandboxApi.createDemobankEbicsSubscriber(
@ -697,7 +746,7 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
let accountInfoResp = await LibeufinSandboxApi.demobankAccountInfo( let accountInfoResp = await LibeufinSandboxApi.demobankAccountInfo(
"admin", "admin",
"secret", "secret",
{ baseUrl: this.baseUrlAccessApi }, { baseUrl: this.bankAccessApiBaseUrl },
accountName, // bank account label. accountName, // bank account label.
); );
return { return {
@ -793,7 +842,7 @@ export class FakebankService
{ {
proc: ProcessWrapper | undefined; proc: ProcessWrapper | undefined;
http = createPlatformHttpLib(); http = createPlatformHttpLib({ allowHttp: true, enableThrottling: false });
// We store "created" accounts during setup and // We store "created" accounts during setup and
// register them after startup. // 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) { for (const acc of accounts) {
await runCommand( await runCommand(
@ -1494,7 +1545,7 @@ export class MerchantApiClient {
) {} ) {}
// FIXME: Migrate everything to this in favor of axios // FIXME: Migrate everything to this in favor of axios
http = createPlatformHttpLib(); http = createPlatformHttpLib({ allowHttp: true, enableThrottling: false });
async changeAuth(auth: MerchantAuthConfiguration): Promise<void> { async changeAuth(auth: MerchantAuthConfiguration): Promise<void> {
const url = new URL("private/auth", this.baseUrl); const url = new URL("private/auth", this.baseUrl);
@ -2052,6 +2103,7 @@ export async function runTestWithState(
try { try {
logger.info("running test in directory", gc.testDir); logger.info("running test in directory", gc.testDir);
await Promise.race([testMain(gc), p.promise]); await Promise.race([testMain(gc), p.promise]);
logger.info("completed test in directory", gc.testDir);
status = "pass"; status = "pass";
if (linger) { if (linger) {
const rl = readline.createInterface({ const rl = readline.createInterface({
@ -2068,9 +2120,22 @@ export async function runTestWithState(
rl.close(); rl.close();
} }
} catch (e) { } catch (e) {
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); console.error("FATAL: test failed with exception", e);
if (e instanceof TalerError) {
console.error(`error detail: ${j2s(e.errorDetail)}`);
} }
status = "fail"; status = "fail";
} finally { } finally {
@ -2243,23 +2308,28 @@ export class WalletCli {
const cryptoWorkerArg = cliOpts.cryptoWorkerType const cryptoWorkerArg = cliOpts.cryptoWorkerType
? `--crypto-worker=${cliOpts.cryptoWorkerType}` ? `--crypto-worker=${cliOpts.cryptoWorkerType}`
: ""; : "";
const resp = await sh( const logName = `wallet-${self.name}`;
self.globalTestState, const command = `taler-wallet-cli ${
`wallet-${self.name}`,
`taler-wallet-cli ${
self.timetravelArg ?? "" self.timetravelArg ?? ""
} ${cryptoWorkerArg} --no-throttle -LTRACE --skip-defaults --wallet-db '${ } ${cryptoWorkerArg} --allow-http --no-throttle -LTRACE --skip-defaults --wallet-db '${
self.dbfile self.dbfile
}' api '${op}' ${shellWrap(JSON.stringify(payload))}`, }' api '${op}' ${shellWrap(JSON.stringify(payload))}`;
); const resp = await sh(self.globalTestState, logName, command);
logger.info("--- wallet core response ---"); logger.info("--- wallet core response ---");
logger.info(resp); logger.info(resp);
logger.info("--- end of response ---"); logger.info("--- end of response ---");
let ar: any; let ar: CoreApiResponse;
try { try {
ar = JSON.parse(resp) as CoreApiResponse; ar = JSON.parse(resp);
} catch (e) { } 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") { if (ar.type === "error") {
throw TalerError.fromUncheckedDetail(ar.error); throw TalerError.fromUncheckedDetail(ar.error);
@ -2295,6 +2365,7 @@ export class WalletCli {
`wallet-${this.name}`, `wallet-${this.name}`,
"taler-wallet-cli", "taler-wallet-cli",
[ [
"--allow-http",
"--no-throttle", "--no-throttle",
...this.timetravelArgArr, ...this.timetravelArgArr,
"-LTRACE", "-LTRACE",
@ -2313,6 +2384,7 @@ export class WalletCli {
`wallet-${this.name}`, `wallet-${this.name}`,
"taler-wallet-cli", "taler-wallet-cli",
[ [
"--allow-http",
"--no-throttle", "--no-throttle",
"--skip-defaults", "--skip-defaults",
"-LTRACE", "-LTRACE",

View File

@ -5,10 +5,9 @@
* the services get actually started and managed. * the services get actually started and managed.
*/ */
import { URL } from "@gnu-taler/taler-util";
import axiosImp from "axios"; import axiosImp from "axios";
const axios = axiosImp.default; const axios = axiosImp.default;
import { AmountString, Logger, URL } from "@gnu-taler/taler-util";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
export interface LibeufinSandboxServiceInterface { export interface LibeufinSandboxServiceInterface {
baseUrl: string; baseUrl: string;

View File

@ -899,6 +899,8 @@ export function findNexusPayment(
): LibeufinNexusMoneyMovement | void { ): LibeufinNexusMoneyMovement | void {
let transactions = payments["transactions"]; let transactions = payments["transactions"];
for (let i = 0; i < transactions.length; i++) { 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"]; let batches = transactions[i]["camtData"]["batches"];
for (let y = 0; y < batches.length; y++) { for (let y = 0; y < batches.length; y++) {
let movements = batches[y]["batchTransactions"]; let movements = batches[y]["batchTransactions"];

View File

@ -17,10 +17,6 @@
/** /**
* Imports. * Imports.
*/ */
import { deepStrictEqual } from "assert";
import fs from "fs";
import os from "os";
import path from "path";
import { import {
addPaytoQueryParams, addPaytoQueryParams,
Amounts, Amounts,
@ -28,33 +24,34 @@ import {
decodeCrock, decodeCrock,
j2s, j2s,
Logger, Logger,
parsePaytoUri,
rsaBlind, rsaBlind,
setGlobalLogLevelFromString, setGlobalLogLevelFromString,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { runBench1 } from "./bench1.js";
import { runBench2 } from "./bench2.js";
import { runBench3 } from "./bench3.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 { clk } from "@gnu-taler/taler-util/clk";
import { createPlatformHttpLib } from "@gnu-taler/taler-util/http"; import { createPlatformHttpLib } from "@gnu-taler/taler-util/http";
import { import {
BankAccessApiClient, BankAccessApiClient,
checkReserve,
CryptoDispatcher, CryptoDispatcher,
downloadExchangeInfo, downloadExchangeInfo,
SynchronousCryptoWorkerFactoryPlain, SynchronousCryptoWorkerFactoryPlain,
topupReserveWithDemobank, topupReserveWithDemobank,
} from "@gnu-taler/taler-wallet-core"; } 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,
runTestWithState,
} from "./harness/harness.js";
import { getTestInfo, runTests } from "./integrationtests/testrunner.js";
import { lintExchangeDeployment } from "./lint.js";
const logger = new Logger("taler-harness:index.ts"); const logger = new Logger("taler-harness:index.ts");
@ -213,6 +210,7 @@ deploymentCli
baseUrl: args.tipTopup.bankAccessUrl, baseUrl: args.tipTopup.bankAccessUrl,
username: args.tipTopup.bankAccount, username: args.tipTopup.bankAccount,
password: args.tipTopup.bankPassword, password: args.tipTopup.bankPassword,
allowHttp: true,
}); });
const paytoUri = addPaytoQueryParams(tipReserveResp.payto_uri, { const paytoUri = addPaytoQueryParams(tipReserveResp.payto_uri, {
@ -495,6 +493,12 @@ testingCli
.flag("experimental", ["--experimental"], { .flag("experimental", ["--experimental"], {
help: "Include tests marked as 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"], { .flag("quiet", ["--quiet"], {
help: "Produce less output.", help: "Produce less output.",
}) })
@ -504,6 +508,8 @@ testingCli
.action(async (args) => { .action(async (args) => {
await runTests({ await runTests({
includePattern: args.runIntegrationtests.pattern, includePattern: args.runIntegrationtests.pattern,
failFast: args.runIntegrationtests.failFast,
waitOnFail: args.runIntegrationtests.waitOnFail,
suiteSpec: args.runIntegrationtests.suites, suiteSpec: args.runIntegrationtests.suites,
dryRun: args.runIntegrationtests.dryRun, dryRun: args.runIntegrationtests.dryRun,
verbosity: args.runIntegrationtests.quiet ? 0 : 1, verbosity: args.runIntegrationtests.quiet ? 0 : 1,

View File

@ -166,6 +166,7 @@ export async function runAgeRestrictionsMerchantTest(t: GlobalTestState) {
wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl,
accountName: exchangeBankAccount.accountName, accountName: exchangeBankAccount.accountName,
accountPassword: exchangeBankAccount.accountPassword, accountPassword: exchangeBankAccount.accountPassword,
allowHttp: true,
}); });
await wireGatewayApiClient.adminAddIncoming({ await wireGatewayApiClient.adminAddIncoming({

View File

@ -18,9 +18,7 @@
* Imports. * Imports.
*/ */
import { AbsoluteTime, Duration } from "@gnu-taler/taler-util"; import { AbsoluteTime, Duration } from "@gnu-taler/taler-util";
import { import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
WalletApiOperation,
} from "@gnu-taler/taler-wallet-core";
import { defaultCoinConfig } from "../harness/denomStructures.js"; import { defaultCoinConfig } from "../harness/denomStructures.js";
import { GlobalTestState, WalletCli } from "../harness/harness.js"; import { GlobalTestState, WalletCli } from "../harness/harness.js";
import { import {

View File

@ -126,6 +126,7 @@ export async function runBankApiTest(t: GlobalTestState) {
wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl,
accountName: exchangeBankAccount.accountName, accountName: exchangeBankAccount.accountName,
accountPassword: exchangeBankAccount.accountPassword, accountPassword: exchangeBankAccount.accountPassword,
allowHttp: true,
}); });
await wireGatewayApiClient.adminAddIncoming({ await wireGatewayApiClient.adminAddIncoming({

View File

@ -33,6 +33,7 @@ import {
refreshCoin, refreshCoin,
SynchronousCryptoWorkerFactoryPlain, SynchronousCryptoWorkerFactoryPlain,
topupReserveWithDemobank, topupReserveWithDemobank,
Wallet,
withdrawCoin, withdrawCoin,
} from "@gnu-taler/taler-wallet-core"; } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js"; import { GlobalTestState } from "../harness/harness.js";
@ -46,7 +47,10 @@ export async function runExchangeDepositTest(t: GlobalTestState) {
const { bank, exchange } = await createSimpleTestkudosEnvironment(t); const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
const http = createPlatformHttpLib(); const http = createPlatformHttpLib({
allowHttp: true,
enableThrottling: false,
});
const cryptiDisp = new CryptoDispatcher( const cryptiDisp = new CryptoDispatcher(
new SynchronousCryptoWorkerFactoryPlain(), new SynchronousCryptoWorkerFactoryPlain(),
); );
@ -71,7 +75,9 @@ export async function runExchangeDepositTest(t: GlobalTestState) {
await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub); 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({ const coin = await withdrawCoin({
http, http,

View File

@ -24,7 +24,10 @@ import {
Duration, Duration,
durationFromSpec, durationFromSpec,
} from "@gnu-taler/taler-util"; } 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 { makeNoFeeCoinConfig } from "../harness/denomStructures.js";
import { import {
BankService, BankService,
@ -65,7 +68,10 @@ async function applyTimeTravel(
} }
} }
const http = createPlatformHttpLib(); const http = createPlatformHttpLib({
allowHttp: true,
enableThrottling: false,
});
/** /**
* Basic time travel test. * Basic time travel test.

View File

@ -340,7 +340,10 @@ export async function runKycTest(t: GlobalTestState) {
// We now simulate the user interacting with the KYC service, // We now simulate the user interacting with the KYC service,
// which would usually done in the browser. // 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 kycServerResp = await httpLib.get(kycNotif.kycUrl);
const kycLoginResp = await kycServerResp.json(); const kycLoginResp = await kycServerResp.json();
console.log("kyc server resp:", j2s(kycLoginResp)); console.log("kyc server resp:", j2s(kycLoginResp));

View File

@ -39,7 +39,10 @@ import {
withdrawViaBank, withdrawViaBank,
} from "../harness/helpers.js"; } from "../harness/helpers.js";
const httpLib = createPlatformHttpLib(); const httpLib = createPlatformHttpLib({
allowHttp: true,
enableThrottling: false,
});
interface Context { interface Context {
merchant: MerchantService; merchant: MerchantService;

View File

@ -61,6 +61,7 @@ export async function runTippingTest(t: GlobalTestState) {
wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl,
accountName: exchangeBankAccount.accountName, accountName: exchangeBankAccount.accountName,
accountPassword: exchangeBankAccount.accountPassword, accountPassword: exchangeBankAccount.accountPassword,
allowHttp: true,
}); });
await wireGatewayApiClient.adminAddIncoming({ await wireGatewayApiClient.adminAddIncoming({

View File

@ -33,6 +33,7 @@ import {
refreshCoin, refreshCoin,
SynchronousCryptoWorkerFactoryPlain, SynchronousCryptoWorkerFactoryPlain,
topupReserveWithDemobank, topupReserveWithDemobank,
Wallet,
withdrawCoin, withdrawCoin,
} from "@gnu-taler/taler-wallet-core"; } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js"; import { GlobalTestState } from "../harness/harness.js";
@ -46,7 +47,10 @@ export async function runWalletDblessTest(t: GlobalTestState) {
const { bank, exchange } = await createSimpleTestkudosEnvironment(t); const { bank, exchange } = await createSimpleTestkudosEnvironment(t);
const http = createPlatformHttpLib(); const http = createPlatformHttpLib({
allowHttp: true,
enableThrottling: false,
});
const cryptiDisp = new CryptoDispatcher( const cryptiDisp = new CryptoDispatcher(
new SynchronousCryptoWorkerFactoryPlain(), new SynchronousCryptoWorkerFactoryPlain(),
); );
@ -84,7 +88,9 @@ export async function runWalletDblessTest(t: GlobalTestState) {
await checkReserve(http, exchange.baseUrl, reserveKeyPair.pub); 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({ const coin = await withdrawCoin({
http, http,
@ -125,8 +131,12 @@ export async function runWalletDblessTest(t: GlobalTestState) {
}); });
const refreshDenoms = [ 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({ await refreshCoin({

View File

@ -73,6 +73,7 @@ export async function runWithdrawalManualTest(t: GlobalTestState) {
wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl, wireGatewayApiBaseUrl: exchangeBankAccount.wireGatewayApiBaseUrl,
accountName: exchangeBankAccount.accountName, accountName: exchangeBankAccount.accountName,
accountPassword: exchangeBankAccount.accountPassword, accountPassword: exchangeBankAccount.accountPassword,
allowHttp: true,
}); });
await wireGatewayApiClient.adminAddIncoming({ await wireGatewayApiClient.adminAddIncoming({

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 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 child_process from "child_process";
import * as fs from "fs"; import * as fs from "fs";
import * as os from "os"; import * as os from "os";
@ -105,6 +105,7 @@ import { runExchangeDepositTest } from "./test-exchange-deposit.js";
/** /**
* Test runner. * Test runner.
*/ */
const logger = new Logger("testrunner.ts");
/** /**
* Spec for one test. * Spec for one test.
@ -199,6 +200,8 @@ export interface TestRunSpec {
includePattern?: string; includePattern?: string;
suiteSpec?: string; suiteSpec?: string;
dryRun?: boolean; dryRun?: boolean;
failFast?: boolean;
waitOnFail?: boolean;
includeExperimental: boolean; includeExperimental: boolean;
noTimeout: boolean; noTimeout: boolean;
verbosity: number; verbosity: number;
@ -357,7 +360,7 @@ export async function runTests(spec: TestRunSpec) {
if (token.isCancelled) { if (token.isCancelled) {
return; return;
} }
console.log(`process exited code=${code} signal=${signal}`); logger.info(`process exited code=${code} signal=${signal}`);
if (signal) { if (signal) {
reject(new Error(`test worker exited with signal ${signal}`)); reject(new Error(`test worker exited with signal ${signal}`));
} else if (code != 0) { } else if (code != 0) {
@ -385,6 +388,10 @@ export async function runTests(spec: TestRunSpec) {
try { try {
result = await token.racePromise(resultPromise); 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) { } catch (e: any) {
console.error(`test ${testName} timed out`); console.error(`test ${testName} timed out`);
if (token.isCancelled) { if (token.isCancelled) {
@ -469,10 +476,9 @@ if (runTestInstrStr && process.argv.includes("__TWCLI_TESTWORKER")) {
const { testRootDir, testName } = JSON.parse( const { testRootDir, testName } = JSON.parse(
runTestInstrStr, runTestInstrStr,
) as RunTestChildInstruction; ) as RunTestChildInstruction;
console.log(`running test ${testName} in worker process`);
process.on("disconnect", () => { process.on("disconnect", () => {
console.log("got disconnect from parent"); logger.trace("got disconnect from parent");
process.exit(3); process.exit(3);
}); });
@ -486,35 +492,36 @@ if (runTestInstrStr && process.argv.includes("__TWCLI_TESTWORKER")) {
} }
if (!process.send) { if (!process.send) {
console.error("can't communicate with parent"); logger.error("can't communicate with parent");
process.exit(2); process.exit(2);
} }
if (!testMain) { if (!testMain) {
console.log(`test ${testName} not found`); logger.info(`test ${testName} not found`);
process.exit(2); process.exit(2);
} }
const testDir = path.join(testRootDir, testName); const testDir = path.join(testRootDir, testName);
console.log(`running test ${testName}`); logger.info(`running test ${testName}`);
const gc = new GlobalTestState({ const gc = new GlobalTestState({
testDir, testDir,
}); });
const testResult = await runTestWithState(gc, testMain, testName); const testResult = await runTestWithState(gc, testMain, testName);
logger.info(`done test ${testName}: ${testResult.status}`);
process.send(testResult); process.send(testResult);
}; };
runTest() runTest()
.then(() => { .then(() => {
console.log(`test ${testName} finished in worker`); logger.trace(`test ${testName} finished in worker`);
if (shouldLingerInTest()) { if (shouldLingerInTest()) {
console.log("lingering ..."); logger.trace("lingering ...");
return; return;
} }
process.exit(0); process.exit(0);
}) })
.catch((e) => { .catch((e) => {
console.log(e); logger.error(e);
process.exit(1); process.exit(1);
}); });
} }

View File

@ -53,7 +53,10 @@ interface PubkeyConf {
masterPublicKey: string; masterPublicKey: string;
} }
const httpLib = createPlatformHttpLib(); const httpLib = createPlatformHttpLib({
enableThrottling: false,
allowHttp: true,
});
interface ShellResult { interface ShellResult {
stdout: string; stdout: string;

View File

@ -1604,6 +1604,7 @@ export class Wallet {
allowHttp: false, allowHttp: false,
}, },
testing: { testing: {
preventThrottling: false,
devModeActive: false, devModeActive: false,
insecureTrustExchange: false, insecureTrustExchange: false,
denomselAllowLate: false, denomselAllowLate: false,