commit f72c1fcc314d534db443e0c50aec42a6810e04f1
parent cbc5ad536599f62f7fdddaf912cca91699ded00e
Author: Florian Dold <dold@taler.net>
Date: Wed, 22 Jul 2026 17:28:13 +0200
wallet: test that a repeated global currency entry changes nothing
The duplicates share a transaction with another write, so the case also covers
that they do not take that write down with them.
Diffstat:
1 file changed, 58 insertions(+), 0 deletions(-)
diff --git a/packages/taler-wallet-core/src/dbtx-conformance-cases.ts b/packages/taler-wallet-core/src/dbtx-conformance-cases.ts
@@ -2782,6 +2782,64 @@ export const conformanceCases: ConformanceCase[] = [
},
{
+ name: "global currency: adding the same entry twice is a no-op",
+ async run(t, runner) {
+ const exch = {
+ currency: "TESTKUDOS",
+ exchangeBaseUrl: "https://exchange.example.com/",
+ exchangeMasterPub: ck("gc-master-1"),
+ };
+ const auditor = {
+ currency: "TESTKUDOS",
+ auditorBaseUrl: "https://auditor.example.com/",
+ auditorPub: ck("gc-auditor-1"),
+ };
+ await runner.runReadWriteTx(async (tx) => {
+ await tx.upsertGlobalCurrencyExchange(exch);
+ await tx.upsertGlobalCurrencyAuditor(auditor);
+ });
+
+ // The duplicates go in the same transaction as a write that must
+ // survive them: on a store keyed by a generated id, a second row for the
+ // same entry violates the unique index, and that takes down everything
+ // else the transaction did.
+ await runner.runReadWriteTx(async (tx) => {
+ await tx.upsertGlobalCurrencyExchange(exch);
+ await tx.upsertGlobalCurrencyAuditor(auditor);
+ await tx.upsertGlobalCurrencyExchange({
+ ...exch,
+ exchangeMasterPub: ck("gc-master-2"),
+ });
+ });
+
+ const exchanges = await runner.runReadWriteTx((tx) =>
+ tx.listGlobalCurrencyExchanges(),
+ );
+ t.equal(
+ exchanges.filter((x) => x.exchangeMasterPub === ck("gc-master-1"))
+ .length,
+ 1,
+ "the duplicate must not have added a row",
+ );
+ t.equal(
+ exchanges.filter((x) => x.exchangeMasterPub === ck("gc-master-2"))
+ .length,
+ 1,
+ "the write alongside the duplicates must have survived",
+ );
+
+ const auditors = await runner.runReadWriteTx((tx) =>
+ tx.listGlobalCurrencyAuditors(),
+ );
+ t.equal(
+ auditors.filter((x) => x.auditorPub === ck("gc-auditor-1")).length,
+ 1,
+ "the duplicate auditor must not have added a row",
+ );
+ },
+ },
+
+ {
name: "transaction meta: the timestamp cursor cannot separate a tie",
async run(t, runner) {
// Timestamps are not unique, and the pagination cursor is a bound on