commit 38e380c5c0ae4db1ab5124dc975138ba89f2dc2a
parent 3819d49e5e4c909a67996b45420326eb698dd4e5
Author: Florian Dold <florian@dold.me>
Date: Fri, 13 Mar 2026 17:30:02 +0100
simplify/fix p2p push test and states
Diffstat:
3 files changed, 129 insertions(+), 116 deletions(-)
diff --git a/packages/taler-harness/src/harness/harness.ts b/packages/taler-harness/src/harness/harness.ts
@@ -331,7 +331,7 @@ export class GlobalTestState {
}
/**
- * @deprecated use {@link assertThrowsAsync} instead
+ * @deprecated use {@link assertThrowsTalerErrorAsync} instead
*/
async assertThrowsTalerErrorAsyncLegacy(
block: Promise<unknown>,
diff --git a/packages/taler-harness/src/integrationtests/test-peer-push.ts b/packages/taler-harness/src/integrationtests/test-peer-push.ts
@@ -124,14 +124,15 @@ export async function runPeerPushTest(t: GlobalTestState) {
t.logStep("P2P push errors");
{
- const ex1 = await t.assertThrowsTalerErrorAsyncLegacy(
- wallet1.call(WalletApiOperation.InitiatePeerPushDebit, {
- partialContractTerms: {
- summary: "(this will fail)",
- amount: "TESTKUDOS:250",
- purse_expiration: purseExpiration,
- },
- }),
+ const ex1 = await t.assertThrowsTalerErrorAsync(
+ async () =>
+ await wallet1.call(WalletApiOperation.InitiatePeerPushDebit, {
+ partialContractTerms: {
+ summary: "(this will fail)",
+ amount: "TESTKUDOS:250",
+ purse_expiration: purseExpiration,
+ },
+ }),
);
t.assertTrue(
ex1.errorDetail.code === TalerErrorCode.WALLET_UNEXPECTED_EXCEPTION,
@@ -139,11 +140,12 @@ export async function runPeerPushTest(t: GlobalTestState) {
// FIXME propagate the error correctly
// t.assertTrue(ex1.errorDetail.code === TalerErrorCode.WALLET_PEER_PUSH_PAYMENT_INSUFFICIENT_BALANCE);
- const unknown_purse = await t.assertThrowsTalerErrorAsyncLegacy(
- wallet1.call(WalletApiOperation.PreparePeerPushCredit, {
- talerUri:
- "taler+http://pay-push/localhost:8081/MQP1DP1J94ZZWNQS7TRDF1KJZ7V8H74CZF41V90FKXBPN5GNRN6G",
- }),
+ const unknown_purse = await t.assertThrowsTalerErrorAsync(
+ async () =>
+ await wallet1.call(WalletApiOperation.PreparePeerPushCredit, {
+ talerUri:
+ "taler+http://pay-push/localhost:8081/MQP1DP1J94ZZWNQS7TRDF1KJZ7V8H74CZF41V90FKXBPN5GNRN6G",
+ }),
);
// FIXME this should fail with a proper error code
t.assertTrue(
@@ -194,49 +196,52 @@ export async function runPeerPushTest(t: GlobalTestState) {
}),
]);
- 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,
- },
- }),
- ]),
+ // The single sender should succeed
+ await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: tx.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ });
+
+ // Wallet 4 never confirmed, but should notice that the P2P payment is gone
+ await wallet4.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare4.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborted,
+ },
+ });
+ // Either wallet 2 succeeds and wallet 3 fails
+ // or vice versa.
+ await 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.Failed,
+ },
+ }),
+ ]),
+ Promise.all([
+ wallet2.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare2.transactionId,
+ txState: {
+ major: TransactionMajorState.Failed,
+ },
+ }),
+ wallet3.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare3.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
]),
- wallet4.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: prepare4.transactionId,
- txState: {
- major: TransactionMajorState.Aborted,
- },
- }),
]);
{
@@ -312,48 +317,47 @@ export async function runPeerPushTest(t: GlobalTestState) {
]);
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,
- },
- }),
- ]),
+
+ await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: tx.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ });
+
+ await 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.Failed,
+ },
+ }),
+ ]),
+ Promise.all([
+ wallet2.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare2.transactionId,
+ txState: {
+ major: TransactionMajorState.Failed,
+ },
+ }),
+ wallet3.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare3.transactionId,
+ txState: {
+ major: TransactionMajorState.Done,
+ },
+ }),
]),
]);
}
- t.logStep("P2P push abort");
- {
+ await t.runSpanAsync("P2P push abort", async () => {
const tx = await initPeerPushDebit("abort");
const [prepare2, prepare3] = await Promise.all(
@@ -372,27 +376,33 @@ export async function runPeerPushTest(t: GlobalTestState) {
transactionId: prepare2.transactionId,
});
- await Promise.all([
- wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: tx.transactionId,
- txState: {
- major: TransactionMajorState.Aborted,
- },
- }),
- wallet2.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: prepare2.transactionId,
- txState: {
- major: TransactionMajorState.Aborted,
- },
- }),
- wallet3.call(WalletApiOperation.TestingWaitTransactionState, {
- transactionId: prepare3.transactionId,
- txState: {
- major: TransactionMajorState.Aborted,
- },
- }),
- ]);
- }
+ t.logStep("waiting for wallet1");
+
+ await wallet1.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: tx.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborted,
+ },
+ });
+
+ t.logStep("waiting for wallet2");
+
+ await wallet2.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare2.transactionId,
+ txState: {
+ major: TransactionMajorState.Failed,
+ },
+ });
+
+ t.logStep("waiting for wallet3");
+
+ await wallet3.call(WalletApiOperation.TestingWaitTransactionState, {
+ transactionId: prepare3.transactionId,
+ txState: {
+ major: TransactionMajorState.Aborted,
+ },
+ });
+ });
await t.runSpanAsync("P2P push abort before create purse", async () => {
// Make sure the reserve can't be created.
diff --git a/packages/taler-wallet-core/src/pay-peer-push-credit.ts b/packages/taler-wallet-core/src/pay-peer-push-credit.ts
@@ -899,7 +899,10 @@ async function processPendingMerge(
switch (rec.status) {
case PeerPushCreditStatus.PendingMergeKycRequired:
case PeerPushCreditStatus.PendingMerge: {
- rec.status = PeerPushCreditStatus.Expired;
+ // Note that we do *not* go to an expired state here,
+ // because we also get a Gone status when the other
+ // wallet aborted the P2P payment.
+ rec.status = PeerPushCreditStatus.Failed;
break;
}
default: