integration tests: various fixes

This commit is contained in:
Florian Dold 2022-08-25 23:35:29 +02:00
parent 499e003ff8
commit 70d0199572
No known key found for this signature in database
GPG Key ID: D2E4F00F29D02A4B
10 changed files with 70 additions and 118 deletions

View File

@ -22,8 +22,8 @@ import { CoinConfig, defaultCoinConfig } from "./harness/denomStructures.js";
import {
GlobalTestState,
setupDb,
FakeBankService,
ExchangeService,
FakebankService,
} from "./harness/harness.js";
/**
@ -35,9 +35,11 @@ import {
export async function runEnv1(t: GlobalTestState): Promise<void> {
const db = await setupDb(t);
const bank = await FakeBankService.create(t, {
const bank = await FakebankService.create(t, {
currency: "TESTKUDOS",
httpPort: 8082,
allowRegistrations: true,
database: db.connStr,
});
const exchange = ExchangeService.create(t, {

View File

@ -775,11 +775,21 @@ class LibEuFinBankService extends BankServiceBase implements BankServiceHandle {
/**
* Implementation of the bank service using the "taler-fakebank-run" tool.
*/
class FakebankService extends BankServiceBase implements BankServiceHandle {
export class FakebankService
extends BankServiceBase
implements BankServiceHandle
{
proc: ProcessWrapper | undefined;
http = new NodeHttpLib();
// We store "created" accounts during setup and
// register them after startup.
private accounts: {
accountName: string;
accountPassword: string;
}[] = [];
static async create(
gc: GlobalTestState,
bc: BankConfig,
@ -791,6 +801,7 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
config.setString("bank", "serve", "http");
config.setString("bank", "max_debt_bank", `${bc.currency}:999999`);
config.setString("bank", "max_debt", bc.maxDebt ?? `${bc.currency}:100`);
config.setString("bank", "ram_limit", `${1024}`);
const cfgFilename = gc.testDir + "/bank.conf";
config.write(cfgFilename);
@ -798,6 +809,9 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
}
setSuggestedExchange(e: ExchangeServiceInterface, exchangePayto: string) {
if (!!this.proc) {
throw Error("Can't set suggested exchange while bank is running.");
}
const config = Configuration.load(this.configFile);
config.setString("bank", "suggested_exchange", e.baseUrl);
config.write(this.configFile);
@ -816,10 +830,10 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
accountName: string,
password: string,
): Promise<HarnessExchangeBankAccount> {
// FIXME: Is there a better place to do this initialization?
await this.start();
await this.pingUntilAvailable();
await BankApi.registerAccount(this, accountName, password);
this.accounts.push({
accountName,
accountPassword: password,
});
return {
accountName: accountName,
accountPassword: password,
@ -833,15 +847,25 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
}
async start(): Promise<void> {
logger.info("starting fakebank");
if (this.proc) {
logger.info("fakebank already running, not starting again");
return;
}
this.proc = this.globalTestState.spawnService(
"taler-fakebank-run",
["-c", this.configFile],
[
"-c",
this.configFile,
"--signup-bonus",
`${this.bankConfig.currency}:100`,
],
"bank",
);
await this.pingUntilAvailable();
for (const acc of this.accounts) {
await BankApi.registerAccount(this, acc.accountName, acc.accountPassword);
}
}
async pingUntilAvailable(): Promise<void> {
@ -853,86 +877,8 @@ class FakebankService extends BankServiceBase implements BankServiceHandle {
// Use libeufin bank instead of pybank.
const useLibeufinBank = false;
/**
* Return a euFin or a pyBank implementation of
* the exported BankService class. This allows
* to "dynamically export" such class depending
* on a particular env variable.
*/
function getBankServiceImpl(): {
prototype: typeof FakebankService.prototype;
create: typeof FakebankService.create;
} {
if (useLibeufinBank)
return {
prototype: LibEuFinBankService.prototype,
create: LibEuFinBankService.create,
};
return {
prototype: FakebankService.prototype,
create: FakebankService.create,
};
}
export type BankService = FakebankService;
export const BankService = getBankServiceImpl();
export class FakeBankService {
proc: ProcessWrapper | undefined;
static fromExistingConfig(gc: GlobalTestState): FakeBankService {
const cfgFilename = gc.testDir + "/bank.conf";
logger.info("reading fakebank config from", cfgFilename);
const config = Configuration.load(cfgFilename);
const bc: FakeBankConfig = {
currency: config.getString("taler", "currency").required(),
httpPort: config.getNumber("bank", "http_port").required(),
};
return new FakeBankService(gc, bc, cfgFilename);
}
static async create(
gc: GlobalTestState,
bc: FakeBankConfig,
): Promise<FakeBankService> {
const config = new Configuration();
setTalerPaths(config, gc.testDir + "/talerhome");
config.setString("taler", "currency", bc.currency);
config.setString("bank", "http_port", `${bc.httpPort}`);
config.setString("bank", "ram_limit", `${1024}`);
const cfgFilename = gc.testDir + "/bank.conf";
config.write(cfgFilename);
return new FakeBankService(gc, bc, cfgFilename);
}
get baseUrl(): string {
return `http://localhost:${this.bankConfig.httpPort}/`;
}
get port() {
return this.bankConfig.httpPort;
}
private constructor(
private globalTestState: GlobalTestState,
private bankConfig: FakeBankConfig,
private configFile: string,
) {}
async start(): Promise<void> {
this.proc = this.globalTestState.spawnService(
"taler-fakebank-run",
["-c", this.configFile],
"fakebank",
);
}
async pingUntilAvailable(): Promise<void> {
// Fakebank doesn't have "/config", so we ping just "/".
const url = `http://localhost:${this.bankConfig.httpPort}/`;
await pingProc(this.proc, url, "bank");
}
}
export type BankService = BankServiceHandle;
export const BankService = FakebankService;
export interface ExchangeConfig {
name: string;

View File

@ -691,8 +691,8 @@ export class LibeufinCli {
): Promise<void> {
const stdout = await sh(
this.globalTestState,
"libeufin-cli-submitpayment",
`libeufin-cli accounts submit-payment` +
"libeufin-cli-submitpayments",
`libeufin-cli accounts submit-payments` +
` --payment-uuid=${paymentUuid}` +
` ${details.nexusBankAccountName}`,
{

View File

@ -43,10 +43,10 @@ export async function runBankApiTest(t: GlobalTestState) {
const db = await setupDb(t);
const bank = await BankService.create(t, {
allowRegistrations: true,
currency: "TESTKUDOS",
database: db.connStr,
httpPort: 8082,
database: db.connStr,
allowRegistrations: true,
});
const exchange = ExchangeService.create(t, {

View File

@ -17,17 +17,9 @@
/**
* Imports.
*/
import {
ConfirmPayResultType,
j2s,
PreparePayResultType,
} from "@gnu-taler/taler-util";
import { Wallet, WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import {
GlobalTestState,
MerchantPrivateApi,
WithAuthorization,
} from "../harness/harness.js";
import { j2s } from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { GlobalTestState } from "../harness/harness.js";
import { createSimpleTestkudosEnvironment } from "../harness/helpers.js";
/**

View File

@ -54,6 +54,7 @@ export async function runWithdrawalAbortBankTest(t: GlobalTestState) {
// Abort it
await BankApi.abortWithdrawalOperation(bank, user, wop);
//await BankApi.confirmWithdrawalOperation(bank, user, wop);
// Withdraw

View File

@ -22,7 +22,7 @@ import {
WalletCli,
setupDb,
ExchangeService,
FakeBankService,
FakebankService,
} from "../harness/harness.js";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
@ -36,9 +36,12 @@ export async function runWithdrawalFakebankTest(t: GlobalTestState) {
const db = await setupDb(t);
const bank = await FakeBankService.create(t, {
const bank = await FakebankService.create(t, {
currency: "TESTKUDOS",
httpPort: 8082,
allowRegistrations: true,
// Not used by fakebank
database: db.connStr,
});
const exchange = ExchangeService.create(t, {

View File

@ -106,7 +106,7 @@ export namespace BankApi {
const url = new URL("testing/register", bank.bankAccessApiBaseUrl);
const resp = await bank.http.postJson(url.href, { username, password });
let paytoUri = `payto://x-taler-bank/localhost/${username}`;
if (resp.status !== 200 && resp.status !== 202) {
if (resp.status !== 200 && resp.status !== 202 && resp.status !== 204) {
logger.error(`${j2s(await resp.json())}`);
throw TalerError.fromDetail(
TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,
@ -209,7 +209,7 @@ export namespace BankApi {
): Promise<void> {
const url = new URL(
`accounts/${bankUser.username}/withdrawals/${wopi.withdrawal_id}/abort`,
bank.baseUrl,
bank.bankAccessApiBaseUrl,
);
const resp = await bank.http.postJson(
url.href,

View File

@ -90,16 +90,21 @@ export async function withdrawTestBalance(
ws: InternalWalletState,
req: WithdrawTestBalanceRequest,
): Promise<void> {
const bankBaseUrl = req.bankBaseUrl;
const amount = req.amount;
const exchangeBaseUrl = req.exchangeBaseUrl;
const bankUser = await registerRandomBankUser(ws.http, bankBaseUrl);
logger.trace(
`Registered bank user, bank access base url ${req.bankAccessApiBaseUrl}`,
);
const bankUser = await registerRandomBankUser(
ws.http,
req.bankAccessApiBaseUrl,
);
logger.trace(`Registered bank user ${JSON.stringify(bankUser)}`);
const wresp = await createDemoBankWithdrawalUri(
ws.http,
bankBaseUrl,
req.bankAccessApiBaseUrl,
bankUser,
amount,
);
@ -112,7 +117,7 @@ export async function withdrawTestBalance(
await confirmBankWithdrawalUri(
ws.http,
bankBaseUrl,
req.bankAccessApiBaseUrl,
bankUser,
wresp.withdrawal_id,
);
@ -133,13 +138,13 @@ function getMerchantAuthHeader(m: MerchantBackendInfo): Record<string, string> {
*/
export async function createDemoBankWithdrawalUri(
http: HttpRequestLibrary,
bankBaseUrl: string,
bankAccessApiBaseUrl: string,
bankUser: BankUser,
amount: AmountString,
): Promise<BankWithdrawalResponse> {
const reqUrl = new URL(
`accounts/${bankUser.username}/withdrawals`,
bankBaseUrl,
bankAccessApiBaseUrl,
).href;
const resp = await http.postJson(
reqUrl,
@ -161,13 +166,13 @@ export async function createDemoBankWithdrawalUri(
async function confirmBankWithdrawalUri(
http: HttpRequestLibrary,
bankBaseUrl: string,
bankAccessApiBaseUrl: string,
bankUser: BankUser,
withdrawalId: string,
): Promise<void> {
const reqUrl = new URL(
`accounts/${bankUser.username}/withdrawals/${withdrawalId}/confirm`,
bankBaseUrl,
bankAccessApiBaseUrl,
).href;
const resp = await http.postJson(
reqUrl,
@ -187,9 +192,9 @@ async function confirmBankWithdrawalUri(
async function registerRandomBankUser(
http: HttpRequestLibrary,
bankBaseUrl: string,
bankAccessApiBaseUrl: string,
): Promise<BankUser> {
const reqUrl = new URL("testing/register", bankBaseUrl).href;
const reqUrl = new URL("testing/register", bankAccessApiBaseUrl).href;
const randId = makeId(8);
const bankUser: BankUser = {
// euFin doesn't allow resource names to have upper case letters.
@ -377,7 +382,7 @@ export async function runIntegrationTest(
await withdrawTestBalance(ws, {
amount: Amounts.stringify(withdrawAmountTwo),
bankBaseUrl: args.bankBaseUrl,
bankAccessApiBaseUrl: args.bankBaseUrl,
bankAccessApiBaseUrl: args.bankAccessApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});

View File

@ -376,6 +376,9 @@ export async function getBankWithdrawalInfo(
`withdrawal-operation/${uriResult.withdrawalOperationId}`,
uriResult.bankIntegrationApiBaseUrl,
);
logger.info(`bank withdrawal status URL: ${reqUrl.href}}`);
const resp = await http.get(reqUrl.href);
const status = await readSuccessResponseJsonOrThrow(
resp,