aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian@dold.me>2023-10-16 13:19:10 +0200
committerFlorian Dold <florian@dold.me>2023-10-16 13:19:10 +0200
commit925a97c2e3a52222cb28b2b64d80c0b01305defe (patch)
treeb0d6ec9e63f4020be59ca2c286166efecfa08ac1
parent9504687813d3ee47131f5b7f66c1426f9ccffd41 (diff)
-fix tests
-rw-r--r--packages/taler-harness/src/harness/harness.ts3
-rw-r--r--packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts15
-rw-r--r--packages/taler-harness/src/integrationtests/test-withdrawal-fakebank.ts6
-rw-r--r--packages/taler-util/src/taler-types.ts2
-rw-r--r--packages/taler-wallet-core/src/dbless.ts25
-rw-r--r--packages/taler-wallet-core/src/operations/pending.ts9
-rw-r--r--packages/taler-wallet-core/src/operations/testing.ts74
-rw-r--r--packages/taler-wallet-core/src/operations/withdraw.ts4
-rw-r--r--packages/taler-wallet-core/src/wallet-api-types.ts19
-rw-r--r--packages/taler-wallet-core/src/wallet.ts15
10 files changed, 123 insertions, 49 deletions
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts
index 65a19959a..c16200933 100644
--- a/packages/taler-harness/src/harness/harness.ts
+++ b/packages/taler-harness/src/harness/harness.ts
@@ -654,6 +654,9 @@ export class FakebankService
return this.baseUrl;
}
+ // FIXME: Why do we have this function at all?
+ // We now have a unified corebank API, we should just use that
+ // to create bank accounts, also for the exchange.
async createExchangeAccount(
accountName: string,
password: string,
diff --git a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts
index 449142809..def2462e0 100644
--- a/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts
+++ b/packages/taler-harness/src/integrationtests/test-timetravel-autorefresh.ts
@@ -136,20 +136,22 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) {
},
);
- await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
-
let p: PendingOperationsResponse;
p = await walletClient.call(WalletApiOperation.GetPendingOperations, {});
console.log("pending operations after first time travel");
console.log(JSON.stringify(p, undefined, 2));
- await withdrawViaBankV2(t, {
+ await walletClient.call(WalletApiOperation.TestingWaitTasksProcessed, {});
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+
+ const wres2 = await withdrawViaBankV2(t, {
walletClient,
bank,
exchange,
amount: "TESTKUDOS:20",
});
+ await wres2.withdrawalFinishedCond;
await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
@@ -165,12 +167,13 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) {
},
);
+ await walletClient.call(WalletApiOperation.TestingWaitTasksProcessed, {});
+ await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
+
// At this point, the original coins should've been refreshed.
// It would be too late to refresh them now, as we're past
// the two year deposit expiration.
- await walletClient.call(WalletApiOperation.TestingWaitTransactionsFinal, {});
-
const orderResp = await merchantClient.createOrder({
order: {
fulfillment_url: "http://example.com",
@@ -195,7 +198,7 @@ export async function runTimetravelAutorefreshTest(t: GlobalTestState) {
t.assertTrue(r.status === PreparePayResultType.PaymentPossible);
const cpr = await walletClient.call(WalletApiOperation.ConfirmPay, {
- proposalId: r.proposalId,
+ transactionId: r.transactionId,
});
t.assertTrue(cpr.type === ConfirmPayResultType.Done);
diff --git a/packages/taler-harness/src/integrationtests/test-withdrawal-fakebank.ts b/packages/taler-harness/src/integrationtests/test-withdrawal-fakebank.ts
index e3057451e..e26d9f964 100644
--- a/packages/taler-harness/src/integrationtests/test-withdrawal-fakebank.ts
+++ b/packages/taler-harness/src/integrationtests/test-withdrawal-fakebank.ts
@@ -55,12 +55,14 @@ export async function runWithdrawalFakebankTest(t: GlobalTestState) {
accountName: "exchange",
accountPassword: "x",
wireGatewayApiBaseUrl: new URL(
- "/accounts/exchange/taler-wire-gateway",
+ "/accounts/exchange/taler-wire-gateway/",
bank.baseUrl,
).href,
accountPaytoUri: "payto://x-taler-bank/localhost/exchange",
});
+ await bank.createExchangeAccount("exchange", "x");
+
await bank.start();
await bank.pingUntilAvailable();
@@ -93,8 +95,6 @@ export async function runWithdrawalFakebankTest(t: GlobalTestState) {
const balResp = await wallet.client.call(WalletApiOperation.GetBalances, {});
t.assertAmountEquals("TESTKUDOS:9.72", balResp.balances[0].available);
-
- await t.shutdown();
}
runWithdrawalFakebankTest.suites = ["wallet"];
diff --git a/packages/taler-util/src/taler-types.ts b/packages/taler-util/src/taler-types.ts
index 551b0652f..4b3a426f5 100644
--- a/packages/taler-util/src/taler-types.ts
+++ b/packages/taler-util/src/taler-types.ts
@@ -1585,7 +1585,7 @@ export const codecForWithdrawResponse = (): Codec<ExchangeWithdrawResponse> =>
.property("ev_sig", codecForBlindedDenominationSignature())
.build("WithdrawResponse");
-export const codecForWithdrawBatchResponse =
+export const codecForExchangeWithdrawBatchResponse =
(): Codec<ExchangeWithdrawBatchResponse> =>
buildCodecForObject<ExchangeWithdrawBatchResponse>()
.property("ev_sigs", codecForList(codecForWithdrawResponse()))
diff --git a/packages/taler-wallet-core/src/dbless.ts b/packages/taler-wallet-core/src/dbless.ts
index 4fc890788..b6b80009f 100644
--- a/packages/taler-wallet-core/src/dbless.ts
+++ b/packages/taler-wallet-core/src/dbless.ts
@@ -49,6 +49,9 @@ import {
Logger,
parsePaytoUri,
UnblindedSignature,
+ ExchangeBatchWithdrawRequest,
+ ExchangeWithdrawBatchResponse,
+ codecForExchangeWithdrawBatchResponse,
} from "@gnu-taler/taler-util";
import {
HttpRequestLibrary,
@@ -165,25 +168,29 @@ export async function withdrawCoin(args: {
value: Amounts.parseOrThrow(denom.value),
});
- const reqBody: ExchangeWithdrawRequest = {
- denom_pub_hash: planchet.denomPubHash,
- reserve_sig: planchet.withdrawSig,
- coin_ev: planchet.coinEv,
+ const reqBody: ExchangeBatchWithdrawRequest = {
+ planchets: [
+ {
+ denom_pub_hash: planchet.denomPubHash,
+ reserve_sig: planchet.withdrawSig,
+ coin_ev: planchet.coinEv,
+ },
+ ],
};
const reqUrl = new URL(
- `reserves/${planchet.reservePub}/withdraw`,
+ `reserves/${planchet.reservePub}/batch-withdraw`,
exchangeBaseUrl,
).href;
- const resp = await http.postJson(reqUrl, reqBody);
- const r = await readSuccessResponseJsonOrThrow(
+ const resp = await http.fetch(reqUrl, { method: "POST", body: reqBody });
+ const rBatch = await readSuccessResponseJsonOrThrow(
resp,
- codecForWithdrawResponse(),
+ codecForExchangeWithdrawBatchResponse(),
);
const ubSig = await cryptoApi.unblindDenominationSignature({
planchet,
- evSig: r.ev_sig,
+ evSig: rBatch.ev_sigs[0].ev_sig,
});
return {
diff --git a/packages/taler-wallet-core/src/operations/pending.ts b/packages/taler-wallet-core/src/operations/pending.ts
index 1819aa1b8..7590280bc 100644
--- a/packages/taler-wallet-core/src/operations/pending.ts
+++ b/packages/taler-wallet-core/src/operations/pending.ts
@@ -101,14 +101,14 @@ async function gatherExchangePending(
case ExchangeEntryDbUpdateStatus.Failed:
return;
}
- const opTag = TaskIdentifiers.forExchangeUpdate(exch);
- let opr = await tx.operationRetries.get(opTag);
+ const opUpdateExchangeTag = TaskIdentifiers.forExchangeUpdate(exch);
+ let opr = await tx.operationRetries.get(opUpdateExchangeTag);
const timestampDue = opr?.retryInfo.nextRetry ?? exch.nextRefreshCheckStamp;
resp.pendingOperations.push({
type: PendingTaskType.ExchangeUpdate,
...getPendingCommon(
ws,
- opTag,
+ opUpdateExchangeTag,
AbsoluteTime.fromPreciseTimestamp(timestampPreciseFromDb(timestampDue)),
),
givesLifeness: false,
@@ -119,11 +119,12 @@ async function gatherExchangePending(
// We only schedule a check for auto-refresh if the exchange update
// was successful.
if (!opr?.lastError) {
+ const opCheckRefreshTag = TaskIdentifiers.forExchangeCheckRefresh(exch);
resp.pendingOperations.push({
type: PendingTaskType.ExchangeCheckRefresh,
...getPendingCommon(
ws,
- opTag,
+ opCheckRefreshTag,
AbsoluteTime.fromPreciseTimestamp(
timestampPreciseFromDb(timestampDue),
),
diff --git a/packages/taler-wallet-core/src/operations/testing.ts b/packages/taler-wallet-core/src/operations/testing.ts
index 607d03470..f5bed13dd 100644
--- a/packages/taler-wallet-core/src/operations/testing.ts
+++ b/packages/taler-wallet-core/src/operations/testing.ts
@@ -74,6 +74,7 @@ import {
import { initiatePeerPushDebit } from "./pay-peer-push-debit.js";
import { OpenedPromise, openPromise } from "../index.js";
import { getTransactionById, getTransactions } from "./transactions.js";
+import { getPendingOperations } from "./pending.js";
const logger = new Logger("operations/testing.ts");
@@ -290,7 +291,7 @@ export async function runIntegrationTest(
corebankApiBaseUrl: args.corebankApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.info("done withdrawing test balance");
const balance = await getBalances(ws);
@@ -305,7 +306,7 @@ export async function runIntegrationTest(
await makePayment(ws, myMerchant, args.amountToSpend, "hello world");
// Wait until the refresh is done
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.trace("withdrawing test balance for refund");
const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`);
@@ -320,7 +321,7 @@ export async function runIntegrationTest(
});
// Wait until the withdraw is done
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
const { orderId: refundOrderId } = await makePayment(
ws,
@@ -344,7 +345,7 @@ export async function runIntegrationTest(
logger.trace("integration test: applied refund");
// Wait until the refund is done
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.trace("integration test: making payment after refund");
@@ -357,12 +358,17 @@ export async function runIntegrationTest(
logger.trace("integration test: make payment done");
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.trace("integration test: all done!");
}
-export async function waitUntilDone(ws: InternalWalletState): Promise<void> {
+/**
+ * Wait until all transactions are in a final state.
+ */
+export async function waitUntilTransactionsFinal(
+ ws: InternalWalletState,
+): Promise<void> {
logger.info("waiting until all transactions are in a final state");
ws.ensureTaskLoopRunning();
let p: OpenedPromise<void> | undefined = undefined;
@@ -410,6 +416,44 @@ export async function waitUntilDone(ws: InternalWalletState): Promise<void> {
logger.info("done waiting until all transactions are in a final state");
}
+/**
+ * Wait until pending work is processed.
+ */
+export async function waitUntilTasksProcessed(
+ ws: InternalWalletState,
+): Promise<void> {
+ logger.info("waiting until pending work is processed");
+ ws.ensureTaskLoopRunning();
+ let p: OpenedPromise<void> | undefined = undefined;
+ const cancelNotifs = ws.addNotificationListener((notif) => {
+ if (!p) {
+ return;
+ }
+ if (notif.type === NotificationType.PendingOperationProcessed) {
+ p.resolve();
+ }
+ });
+ while (1) {
+ p = openPromise();
+ const pendingTasksResp = await getPendingOperations(ws);
+ logger.info(`waiting on pending ops: ${j2s(pendingTasksResp)}`);
+ let finished = true;
+ for (const task of pendingTasksResp.pendingOperations) {
+ if (task.isDue) {
+ finished = false;
+ }
+ logger.info(`continuing waiting for task ${task.id}`);
+ }
+ if (finished) {
+ break;
+ }
+ // Wait until task is done
+ await p.promise;
+ }
+ logger.info("done waiting until pending work is processed");
+ cancelNotifs();
+}
+
export async function waitUntilRefreshesDone(
ws: InternalWalletState,
): Promise<void> {
@@ -463,7 +507,7 @@ export async function waitUntilRefreshesDone(
logger.info("done waiting until all refreshes are in a final state");
}
-async function waitUntilPendingReady(
+async function waitUntilTransactionPendingReady(
ws: InternalWalletState,
transactionId: string,
): Promise<void> {
@@ -560,7 +604,7 @@ export async function runIntegrationTest2(
corebankApiBaseUrl: args.corebankApiBaseUrl,
exchangeBaseUrl: args.exchangeBaseUrl,
});
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.info("done withdrawing test balance");
const balance = await getBalances(ws);
@@ -580,7 +624,7 @@ export async function runIntegrationTest2(
);
// Wait until the refresh is done
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.trace("withdrawing test balance for refund");
const withdrawAmountTwo = Amounts.parseOrThrow(`${currency}:18`);
@@ -595,7 +639,7 @@ export async function runIntegrationTest2(
});
// Wait until the withdraw is done
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
const { orderId: refundOrderId } = await makePayment(
ws,
@@ -619,7 +663,7 @@ export async function runIntegrationTest2(
logger.trace("integration test: applied refund");
// Wait until the refund is done
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.trace("integration test: making payment after refund");
@@ -632,7 +676,7 @@ export async function runIntegrationTest2(
logger.trace("integration test: make payment done");
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
const peerPushInit = await initiatePeerPushDebit(ws, {
partialContractTerms: {
@@ -647,7 +691,7 @@ export async function runIntegrationTest2(
},
});
- await waitUntilPendingReady(ws, peerPushInit.transactionId);
+ await waitUntilTransactionPendingReady(ws, peerPushInit.transactionId);
const peerPushCredit = await preparePeerPushCredit(ws, {
talerUri: peerPushInit.talerUri,
@@ -670,7 +714,7 @@ export async function runIntegrationTest2(
},
});
- await waitUntilPendingReady(ws, peerPullInit.transactionId);
+ await waitUntilTransactionPendingReady(ws, peerPullInit.transactionId);
const peerPullInc = await preparePeerPullDebit(ws, {
talerUri: peerPullInit.talerUri,
@@ -680,7 +724,7 @@ export async function runIntegrationTest2(
peerPullDebitId: peerPullInc.peerPullDebitId,
});
- await waitUntilDone(ws);
+ await waitUntilTransactionsFinal(ws);
logger.trace("integration test: all done!");
}
diff --git a/packages/taler-wallet-core/src/operations/withdraw.ts b/packages/taler-wallet-core/src/operations/withdraw.ts
index 2c9c95d4c..5f728b6f5 100644
--- a/packages/taler-wallet-core/src/operations/withdraw.ts
+++ b/packages/taler-wallet-core/src/operations/withdraw.ts
@@ -33,7 +33,7 @@ import {
codecForReserveStatus,
codecForTalerConfigResponse,
codecForWalletKycUuid,
- codecForWithdrawBatchResponse,
+ codecForExchangeWithdrawBatchResponse,
codecForWithdrawOperationStatusResponse,
codecForWithdrawResponse,
CoinStatus,
@@ -939,7 +939,7 @@ async function processPlanchetExchangeBatchRequest(
}
const r = await readSuccessResponseJsonOrThrow(
resp,
- codecForWithdrawBatchResponse(),
+ codecForExchangeWithdrawBatchResponse(),
);
return {
coinIdxs: requestCoinIdxs,
diff --git a/packages/taler-wallet-core/src/wallet-api-types.ts b/packages/taler-wallet-core/src/wallet-api-types.ts
index fadc7aa7f..a8de9ac03 100644
--- a/packages/taler-wallet-core/src/wallet-api-types.ts
+++ b/packages/taler-wallet-core/src/wallet-api-types.ts
@@ -224,6 +224,7 @@ export enum WalletApiOperation {
DeleteStoredBackup = "deleteStoredBackup",
RecoverStoredBackup = "recoverStoredBackup",
UpdateExchangeEntry = "updateExchangeEntry",
+ TestingWaitTasksProcessed = "testingWaitTasksProcessed",
}
// group: Initialization
@@ -1007,7 +1008,7 @@ export type TestingSetTimetravelOp = {
/**
* Wait until all transactions are in a final state.
*/
-export type TestingWaitTransactionsFinal = {
+export type TestingWaitTransactionsFinalOp = {
op: WalletApiOperation.TestingWaitTransactionsFinal;
request: EmptyObject;
response: EmptyObject;
@@ -1016,13 +1017,22 @@ export type TestingWaitTransactionsFinal = {
/**
* Wait until all refresh transactions are in a final state.
*/
-export type TestingWaitRefreshesFinal = {
+export type TestingWaitRefreshesFinalOp = {
op: WalletApiOperation.TestingWaitRefreshesFinal;
request: EmptyObject;
response: EmptyObject;
};
/**
+ * Wait until all tasks have been processed and the wallet is idle.
+ */
+export type TestingWaitTasksProcessedOp = {
+ op: WalletApiOperation.TestingWaitTasksProcessed;
+ request: EmptyObject;
+ response: EmptyObject;
+};
+
+/**
* Wait until a transaction is in a particular state.
*/
export type TestingWaitTransactionStateOp = {
@@ -1132,8 +1142,9 @@ export type WalletOperations = {
[WalletApiOperation.Recycle]: RecycleOp;
[WalletApiOperation.ApplyDevExperiment]: ApplyDevExperimentOp;
[WalletApiOperation.ValidateIban]: ValidateIbanOp;
- [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinal;
- [WalletApiOperation.TestingWaitRefreshesFinal]: TestingWaitRefreshesFinal;
+ [WalletApiOperation.TestingWaitTransactionsFinal]: TestingWaitTransactionsFinalOp;
+ [WalletApiOperation.TestingWaitRefreshesFinal]: TestingWaitRefreshesFinalOp;
+ [WalletApiOperation.TestingWaitTasksProcessed]: TestingWaitTasksProcessedOp;
[WalletApiOperation.TestingSetTimetravel]: TestingSetTimetravelOp;
[WalletApiOperation.TestingWaitTransactionState]: TestingWaitTransactionStateOp;
[WalletApiOperation.GetCurrencySpecification]: GetCurrencySpecificationOp;
diff --git a/packages/taler-wallet-core/src/wallet.ts b/packages/taler-wallet-core/src/wallet.ts
index a8c2895f8..06d9bb9e8 100644
--- a/packages/taler-wallet-core/src/wallet.ts
+++ b/packages/taler-wallet-core/src/wallet.ts
@@ -252,9 +252,10 @@ import {
runIntegrationTest2,
testPay,
waitTransactionState,
- waitUntilDone,
+ waitUntilTransactionsFinal,
waitUntilRefreshesDone,
withdrawTestBalance,
+ waitUntilTasksProcessed,
} from "./operations/testing.js";
import {
acceptTip,
@@ -927,9 +928,9 @@ async function dumpCoins(ws: InternalWalletState): Promise<CoinDumpJson> {
ageCommitmentProof: c.ageCommitmentProof,
spend_allocation: c.spendAllocation
? {
- amount: c.spendAllocation.amount,
- id: c.spendAllocation.id,
- }
+ amount: c.spendAllocation.amount,
+ id: c.spendAllocation.id,
+ }
: undefined,
});
}
@@ -1427,6 +1428,10 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
await waitTransactionState(ws, req.transactionId, req.txState);
return {};
}
+ case WalletApiOperation.TestingWaitTasksProcessed: {
+ await waitUntilTasksProcessed(ws);
+ return {};
+ }
case WalletApiOperation.GetCurrencySpecification: {
// Ignore result, just validate in this mock implementation
const req = codecForGetCurrencyInfoRequest().decode(payload);
@@ -1600,7 +1605,7 @@ async function dispatchRequestInternal<Op extends WalletApiOperation>(
return getVersion(ws);
}
case WalletApiOperation.TestingWaitTransactionsFinal:
- return await waitUntilDone(ws);
+ return await waitUntilTransactionsFinal(ws);
case WalletApiOperation.TestingWaitRefreshesFinal:
return await waitUntilRefreshesDone(ws);
case WalletApiOperation.TestingSetTimetravel: {