commit 78b715dc4b302cd1a79ccf001c83a6630fcf5cf9
parent d80a79a8ea7dd60009c5b11a4f996ca58c822628
Author: Antoine A <>
Date: Wed, 30 Apr 2025 20:05:58 +0200
harness: improve P2P tests
Diffstat:
2 files changed, 179 insertions(+), 43 deletions(-)
diff --git a/packages/taler-harness/src/integrationtests/test-peer-pull.ts b/packages/taler-harness/src/integrationtests/test-peer-pull.ts
@@ -75,8 +75,8 @@ export async function runPeerPullTest(t: GlobalTestState) {
await withdrawRes.withdrawalFinishedCond;
}));
- async function init_peer_pull_credit(w: WalletClient, summary: string, amount: AmountString = "TESTKUDOS:2"): Promise<TransactionPeerPullCredit> {
- const initiate = await w.call(
+ async function initPeerPullCredit(summary: string, amount: AmountString = "TESTKUDOS:2"): Promise<TransactionPeerPullCredit> {
+ const initiate = await wallet1.call(
WalletApiOperation.InitiatePeerPullCredit,
{
exchangeBaseUrl: exchange.baseUrl,
@@ -88,7 +88,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
},
);
- await w.call(WalletApiOperation.TestingWaitTransactionState, {
+ await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
transactionId: initiate.transactionId,
txState: {
major: TransactionMajorState.Pending,
@@ -96,7 +96,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
},
});
- const tx = await w.call(WalletApiOperation.GetTransactionById, {
+ const tx = await wallet1.call(WalletApiOperation.GetTransactionById, {
transactionId: initiate.transactionId,
});
t.assertDeepEqual(tx.type, TransactionType.PeerPullCredit);
@@ -137,7 +137,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
t.logStep("P2P pull errors");
{
- const tx = await init_peer_pull_credit(wallet1, "confirm", "TESTKUDOS:1000");
+ const tx = await initPeerPullCredit("confirm", "TESTKUDOS:1000");
const insufficient_balance = await t.assertThrowsTalerErrorAsync(wallet1.call(
WalletApiOperation.PreparePeerPullDebit,
{ talerUri: tx.talerUri! }
@@ -154,7 +154,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
t.logStep("P2P pull confirm");
{
- const tx = await init_peer_pull_credit(wallet1, "confirm");
+ const tx = await initPeerPullCredit("confirm");
const [prepare2, prepare3, prepare4] = await Promise.all([wallet2, wallet3, wallet4].map(w =>
w.call(
@@ -224,7 +224,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
t.logStep("P2P pull self");
{
- const tx = await init_peer_pull_credit(wallet1, "self");
+ const tx = await initPeerPullCredit("self");
const prepare = await wallet1.call(
WalletApiOperation.PreparePeerPullDebit,
{ talerUri: tx.talerUri! }
@@ -256,7 +256,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
t.logStep("P2P pull conflict");
{
- const tx = await init_peer_pull_credit(wallet1, "conflict");
+ const tx = await initPeerPullCredit("conflict");
const [prepare2, prepare3] = await Promise.all([wallet2, wallet3].map(w =>
w.call(
@@ -319,7 +319,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
t.logStep("P2P pull abort");
{
- const tx = await init_peer_pull_credit(wallet1, "abort");
+ const tx = await initPeerPullCredit("abort");
const [prepare2, prepare3] = await Promise.all([wallet2, wallet3].map(w =>
w.call(
@@ -365,9 +365,46 @@ export async function runPeerPullTest(t: GlobalTestState) {
t.assertTrue(aborted_contract.errorDetail.code === TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION);
}
+ t.logStep("P2P pull abort before create purse");
+ {
+ // Make sure the reserve can't be created.
+ // This will test the case where the transaction is aborted
+ // before the purse could even have been created.
+ await exchange.stop();
+ const initiate = await wallet1.call(
+ WalletApiOperation.InitiatePeerPullCredit,
+ {
+ exchangeBaseUrl: exchange.baseUrl,
+ partialContractTerms: {
+ summary: "abort before purse creation",
+ amount: "TESTKUDOS:5",
+ purse_expiration,
+ },
+ },
+ );
+ await wallet1.call(WalletApiOperation.AbortTransaction, {
+ transactionId: initiate.transactionId,
+ });
+ await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: initiate.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborting,
+ minor: TransactionMinorState.DeletePurse,
+ },
+ });
+ // Restart the exchange for the remainder of the test
+ await exchange.start();
+ await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: initiate.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborted,
+ },
+ });
+ }
+
t.logStep("P2P pull expire");
{
- const tx = await init_peer_pull_credit(wallet1, "expire");
+ const tx = await initPeerPullCredit("expire");
const [prepare2, prepare3] = await Promise.all([wallet2, wallet3].map(w =>
w.call(
@@ -382,9 +419,7 @@ export async function runPeerPullTest(t: GlobalTestState) {
await exchange.stop();
exchange.setTimetravel(timetravelOffsetMs);
- await exchange.start();
- await exchange.pingUntilAvailable();
- await exchange.runExpireOnce();
+ await Promise.all([exchange.start(), exchange.runExpireOnce()]);
await Promise.all([wallet1, wallet2, wallet3].map(w =>
w.call(WalletApiOperation.TestingSetTimetravel, {
@@ -423,6 +458,24 @@ export async function runPeerPullTest(t: GlobalTestState) {
));
t.assertTrue(expired_purse.errorDetail.code === TalerErrorCode.WALLET_PEER_PULL_DEBIT_PURSE_GONE);
}
+
+ await t.runSpanAsync("P2P pull delete", async () => {
+ const delAll = async (w: WalletClient) => {
+ const txn1 = await w.call(WalletApiOperation.GetTransactionsV2, {
+ includeAll: true,
+ });
+ for (const txn of txn1.transactions) {
+ await w.call(WalletApiOperation.DeleteTransaction, {
+ transactionId: txn.transactionId,
+ });
+ }
+ const txn2 = await w.call(WalletApiOperation.GetTransactionsV2, {
+ includeAll: true,
+ });
+ t.assertDeepEqual(txn2.transactions.length, 0);
+ };
+ await Promise.all([wallet1, wallet2, wallet3, wallet4].map(delAll))
+ });
}
runPeerPullTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/test-peer-push.ts b/packages/taler-harness/src/integrationtests/test-peer-push.ts
@@ -68,7 +68,6 @@ export async function runPeerPushTest(t: GlobalTestState) {
await withdrawRes.withdrawalFinishedCond;
async function initPeerPushDebit(
- w: WalletClient,
summary: string,
amount: AmountString = "TESTKUDOS:5",
): Promise<TransactionPeerPushDebit> {
@@ -149,13 +148,13 @@ export async function runPeerPushTest(t: GlobalTestState) {
// FIXME this should fail with a proper error code
t.assertTrue(
unknown_purse.errorDetail.code ===
- TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
+ TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
);
}
t.logStep("P2P push confirm");
{
- const tx = await initPeerPushDebit(wallet1, "confirm");
+ const tx = await initPeerPushDebit("confirm");
// Check balance update
{
@@ -178,14 +177,12 @@ export async function runPeerPushTest(t: GlobalTestState) {
t.assertTrue(prepare2.transactionId === idempotent.transactionId);
}
- await Promise.all([
- wallet2.call(WalletApiOperation.ConfirmPeerPushCredit, {
- transactionId: prepare2.transactionId,
- }),
- wallet3.call(WalletApiOperation.ConfirmPeerPushCredit, {
- transactionId: prepare3.transactionId,
- }),
- ]);
+ await wallet2.call(WalletApiOperation.ConfirmPeerPushCredit, {
+ transactionId: prepare2.transactionId,
+ });
+ await wallet3.call(WalletApiOperation.ConfirmPeerPushCredit, {
+ transactionId: prepare3.transactionId,
+ });
// Idempotent
await Promise.all([
@@ -258,9 +255,104 @@ export async function runPeerPushTest(t: GlobalTestState) {
// FIXME this should also fail
}
+ t.logStep("P2P pull self");
+ {
+ const tx = await initPeerPushDebit("self");
+ const prepare = await wallet1.call(
+ WalletApiOperation.PreparePeerPushCredit,
+ { talerUri: tx.talerUri! }
+ );
+ await wallet1.call(WalletApiOperation.ConfirmPeerPushCredit, {
+ transactionId: prepare.transactionId,
+ })
+ await Promise.all([
+ wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: tx.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
+ wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
+ ]);
+
+ // Check scan after completion
+ const idempotent = await wallet1.call(WalletApiOperation.PreparePeerPushCredit,
+ { talerUri: tx.talerUri! }
+ );
+ t.assertTrue(prepare.transactionId === idempotent.transactionId);
+ }
+
+ t.logStep("P2P pull conflict");
+ {
+ const tx = await initPeerPushDebit("conflict");
+
+ const [prepare2, prepare3] = await Promise.all([wallet2, wallet3].map(w =>
+ w.call(
+ WalletApiOperation.PreparePeerPushCredit,
+ { talerUri: tx.talerUri! }
+ ))
+ );
+
+ await exchange.stop();
+
+ await Promise.all([
+ wallet2.call(WalletApiOperation.ConfirmPeerPushCredit, {
+ transactionId: prepare2.transactionId,
+ }),
+ wallet3.call(WalletApiOperation.ConfirmPeerPushCredit, {
+ transactionId: prepare3.transactionId,
+ }),
+ ]);
+
+ await exchange.start()
+ await Promise.all([
+ wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: tx.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
+ Promise.race([
+ Promise.all([
+ wallet2.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare2.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
+ wallet3.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare3.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborted,
+ },
+ }),
+ ]),
+ Promise.all([
+ wallet2.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare2.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborted,
+ },
+ }),
+ wallet3.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare3.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
+ ])
+ ])
+ ]);
+ }
+
t.logStep("P2P push abort");
{
- const tx = await initPeerPushDebit(wallet1, "abort");
+ const tx = await initPeerPushDebit("abort");
const [prepare2, prepare3] = await Promise.all(
[wallet2, wallet3].map((w) =>
@@ -298,9 +390,6 @@ export async function runPeerPushTest(t: GlobalTestState) {
},
}),
]);
-
- const bal = await wallet1.call(WalletApiOperation.GetBalances, {});
- t.assertAmountEquals(bal.balances[0].available, "TESTKUDOS:189.99");
}
await t.runSpanAsync("P2P push abort before create purse", async () => {
@@ -308,21 +397,21 @@ export async function runPeerPushTest(t: GlobalTestState) {
// This will test the case where the transaction is aborted
// before the purse could even have been created.
await exchange.stop();
- const initResp = await wallet1.call(
+ const initiate = await wallet1.call(
WalletApiOperation.InitiatePeerPushDebit,
{
partialContractTerms: {
- summary: "foo",
+ summary: "abort before purse creation",
amount: "TESTKUDOS:5",
purse_expiration: purseExpiration,
},
},
);
await wallet1.call(WalletApiOperation.AbortTransaction, {
- transactionId: initResp.transactionId,
+ transactionId: initiate.transactionId,
});
await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: initResp.transactionId,
+ transactionId: initiate.transactionId,
txState: {
major: TransactionMajorState.Aborting,
minor: TransactionMinorState.DeletePurse,
@@ -331,7 +420,7 @@ export async function runPeerPushTest(t: GlobalTestState) {
// Restart the exchange for the remainder of the test
await exchange.start();
await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: initResp.transactionId,
+ transactionId: initiate.transactionId,
txState: {
major: TransactionMajorState.Aborted,
},
@@ -340,7 +429,7 @@ export async function runPeerPushTest(t: GlobalTestState) {
t.logStep("P2P push expire");
{
- const tx = await initPeerPushDebit(wallet1, "expire");
+ const tx = await initPeerPushDebit("expire");
const [prepare2, prepare3] = await Promise.all(
[wallet2, wallet3].map((w) =>
@@ -356,9 +445,7 @@ export async function runPeerPushTest(t: GlobalTestState) {
await exchange.stop();
exchange.setTimetravel(timetravelOffsetMs);
- await exchange.start();
- await exchange.pingUntilAvailable();
- await exchange.runExpireOnce();
+ await Promise.all([exchange.start(), exchange.runExpireOnce()]);
await Promise.all(
[wallet1, wallet2, wallet3].map((w) =>
@@ -398,7 +485,7 @@ export async function runPeerPushTest(t: GlobalTestState) {
// Test deleting p2p transaction.
// Tests against a regression.
- await t.runSpanAsync("delete-transactions", async () => {
+ await t.runSpanAsync("P2P push delete", async () => {
const delAll = async (w: WalletClient) => {
const txn1 = await w.call(WalletApiOperation.GetTransactionsV2, {
includeAll: true,
@@ -413,12 +500,8 @@ export async function runPeerPushTest(t: GlobalTestState) {
});
t.assertDeepEqual(txn2.transactions.length, 0);
};
- await delAll(wallet1);
- await delAll(wallet2);
- await delAll(wallet3);
- await delAll(wallet4);
+ await Promise.all([wallet1, wallet2, wallet3, wallet4].map(delAll))
});
}
runPeerPushTest.suites = ["wallet"];
-runPeerPushTest.timeoutMs = 120000;