gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: fix non-termination in run-un


From: gnunet
Subject: [taler-wallet-core] branch master updated: fix non-termination in run-until done
Date: Sun, 18 Feb 2024 23:34:57 +0100

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new b55bf0779 fix non-termination in run-until done
b55bf0779 is described below

commit b55bf0779946b6a1554a687e05841d131b9951b3
Author: Florian Dold <florian@dold.me>
AuthorDate: Sun Feb 18 23:34:57 2024 +0100

    fix non-termination in run-until done
    
    Also add a test for this.
---
 .../test-wallet-cli-termination.ts                 | 101 +++++++++++++++++++++
 .../src/integrationtests/testrunner.ts             |   2 +
 packages/taler-wallet-core/src/shepherd.ts         |  48 +++++++++-
 3 files changed, 148 insertions(+), 3 deletions(-)

diff --git 
a/packages/taler-harness/src/integrationtests/test-wallet-cli-termination.ts 
b/packages/taler-harness/src/integrationtests/test-wallet-cli-termination.ts
new file mode 100644
index 000000000..4f015799f
--- /dev/null
+++ b/packages/taler-harness/src/integrationtests/test-wallet-cli-termination.ts
@@ -0,0 +1,101 @@
+/*
+ This file is part of GNU Taler
+ (C) 2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Imports.
+ */
+import { AmountString } from "@gnu-taler/taler-util";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { CoinConfig, defaultCoinConfig } from "../harness/denomStructures.js";
+import {
+  BankService,
+  ExchangeService,
+  GlobalTestState,
+  MerchantService,
+  WalletCli,
+  generateRandomPayto,
+  setupDb,
+} from "../harness/harness.js";
+
+/**
+ * Test that run-until-done of taler-wallet-cli terminates.
+ */
+export async function runWalletCliTerminationTest(t: GlobalTestState) {
+  const db = await setupDb(t);
+
+  const coinConfig: CoinConfig[] = defaultCoinConfig.map((x) => 
x("TESTKUDOS"));
+
+  const bank = await BankService.create(t, {
+    allowRegistrations: true,
+    currency: "TESTKUDOS",
+    database: db.connStr,
+    httpPort: 8082,
+  });
+
+  const exchange = ExchangeService.create(t, {
+    name: "testexchange-1",
+    currency: "TESTKUDOS",
+    httpPort: 8081,
+    database: db.connStr,
+  });
+
+  const merchant = await MerchantService.create(t, {
+    name: "testmerchant-1",
+    currency: "TESTKUDOS",
+    httpPort: 8083,
+    database: db.connStr,
+  });
+
+  const exchangeBankAccount = await bank.createExchangeAccount(
+    "myexchange",
+    "x",
+  );
+  exchange.addBankAccount("1", exchangeBankAccount);
+
+  bank.setSuggestedExchange(exchange, exchangeBankAccount.accountPaytoUri);
+
+  await bank.start();
+
+  await bank.pingUntilAvailable();
+
+  exchange.addCoinConfigList(coinConfig);
+
+  await exchange.start();
+  await exchange.pingUntilAvailable();
+
+  merchant.addExchange(exchange);
+
+  await merchant.start();
+  await merchant.pingUntilAvailable();
+
+  await merchant.addInstanceWithWireAccount({
+    id: "default",
+    name: "Default Instance",
+    paytoUris: [generateRandomPayto("merchant-default")],
+  });
+
+  const wallet = new WalletCli(t, "wallet");
+
+  await wallet.client.call(WalletApiOperation.WithdrawTestBalance, {
+    corebankApiBaseUrl: bank.corebankApiBaseUrl,
+    exchangeBaseUrl: exchange.baseUrl,
+    amount: "TESTKUDOS:20" as AmountString,
+  });
+
+  await wallet.runUntilDone();
+}
+
+runWalletCliTerminationTest.suites = ["wallet"];
diff --git a/packages/taler-harness/src/integrationtests/testrunner.ts 
b/packages/taler-harness/src/integrationtests/testrunner.ts
index 624b230d3..f4401c63c 100644
--- a/packages/taler-harness/src/integrationtests/testrunner.ts
+++ b/packages/taler-harness/src/integrationtests/testrunner.ts
@@ -86,6 +86,7 @@ import { runTermOfServiceFormatTest } from 
"./test-tos-format.js";
 import { runWalletBackupBasicTest } from "./test-wallet-backup-basic.js";
 import { runWalletBackupDoublespendTest } from 
"./test-wallet-backup-doublespend.js";
 import { runWalletBalanceTest } from "./test-wallet-balance.js";
+import { runWalletCliTerminationTest } from "./test-wallet-cli-termination.js";
 import { runWalletCryptoWorkerTest } from "./test-wallet-cryptoworker.js";
 import { runWalletDblessTest } from "./test-wallet-dbless.js";
 import { runWalletDd48Test } from "./test-wallet-dd48.js";
@@ -189,6 +190,7 @@ const allTests: TestMainFunction[] = [
   runWalletDd48Test,
   runCurrencyScopeTest,
   runWalletRefreshTest,
+  runWalletCliTerminationTest,
   runOtpTest,
 ];
 
diff --git a/packages/taler-wallet-core/src/shepherd.ts 
b/packages/taler-wallet-core/src/shepherd.ts
index 4aea2d15d..a3735e78f 100644
--- a/packages/taler-wallet-core/src/shepherd.ts
+++ b/packages/taler-wallet-core/src/shepherd.ts
@@ -77,6 +77,32 @@ interface ShepherdInfo {
   cts: CancellationToken.Source;
 }
 
+/**
+ * Check if a task is alive, i.e. whether it prevents
+ * the main task loop from exiting.
+ */
+function taskGivesLiveness(taskId: string): boolean {
+  const parsedTaskId = parseTaskIdentifier(taskId);
+  switch (parsedTaskId.tag) {
+    case PendingTaskType.Backup:
+    case PendingTaskType.ExchangeUpdate:
+      return false;
+    case PendingTaskType.Deposit:
+    case PendingTaskType.PeerPullCredit:
+    case PendingTaskType.PeerPullDebit:
+    case PendingTaskType.PeerPushCredit:
+    case PendingTaskType.Refresh:
+    case PendingTaskType.Recoup:
+    case PendingTaskType.RewardPickup:
+    case PendingTaskType.Withdraw:
+    case PendingTaskType.PeerPushDebit:
+    case PendingTaskType.Purchase:
+      return true;
+    default:
+      assertUnreachable(parsedTaskId);
+  }
+}
+
 export class TaskScheduler {
   private sheps: Map<TaskId, ShepherdInfo> = new Map();
 
@@ -89,6 +115,8 @@ export class TaskScheduler {
   async loadTasksFromDb(): Promise<void> {
     const activeTasks = await getActiveTaskIds(this.ws);
 
+    logger.info(`active tasks from DB: ${j2s(activeTasks)}`);
+
     for (const tid of activeTasks.taskIds) {
       this.startShepherdTask(tid);
     }
@@ -98,10 +126,24 @@ export class TaskScheduler {
     logger.info("Running task loop.");
     this.ws.isTaskLoopRunning = true;
     await this.loadTasksFromDb();
+    logger.info("loaded!");
+    logger.info(`sheps: ${this.sheps.size}`);
     while (true) {
-      if (opts.stopWhenDone && this.sheps.size === 0) {
-        logger.info("Breaking out of task loop (no more work).");
-        break;
+      if (opts.stopWhenDone) {
+        let alive = false;
+        const taskIds = [...this.sheps.keys()];
+        logger.info(`current task IDs: ${j2s(taskIds)}`);
+        logger.info(`sheps: ${this.sheps.size}`);
+        for (const taskId of taskIds) {
+          if (taskGivesLiveness(taskId)) {
+            alive = true;
+            break;
+          }
+        }
+        if (!alive) {
+          logger.info("Breaking out of task loop (no more work).");
+          break;
+        }
       }
       if (this.ws.stopped) {
         logger.info("Breaking out of task loop (wallet stopped).");

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]