gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: integrate purse expiration into


From: gnunet
Subject: [taler-exchange] branch master updated: integrate purse expiration into test, bugfixes
Date: Tue, 17 May 2022 11:21:23 +0200

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new d8f1f7b7 integrate purse expiration into test, bugfixes
d8f1f7b7 is described below

commit d8f1f7b761a41fc027c53dcd85c2b07dd73c6d1b
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Tue May 17 11:21:20 2022 +0200

    integrate purse expiration into test, bugfixes
---
 debian/taler-exchange.install                  |   4 +
 src/exchange/taler-exchange-expire.c           |  41 +++++--
 src/exchange/taler-exchange-httpd.h            |   4 +-
 src/exchange/taler-exchange-httpd_purses_get.c |  31 +++++
 src/exchangedb/common-0001.sql                 |   8 ++
 src/exchangedb/exchange-0001-part.sql          |  29 ++---
 src/include/taler_testing_lib.h                |  24 ++++
 src/lib/exchange_api_purses_get.c              |   5 +
 src/testing/Makefile.am                        |   2 +
 src/testing/test_exchange_api-cs.conf          |   8 ++
 src/testing/test_exchange_api-rsa.conf         |   9 ++
 src/testing/test_exchange_p2p.c                |  58 +++++++++
 src/testing/testing_api_cmd_exec_expire.c      | 162 +++++++++++++++++++++++++
 src/testing/testing_api_cmd_exec_router.c      | 161 ++++++++++++++++++++++++
 src/testing/testing_api_cmd_purse_get.c        |   1 +
 15 files changed, 521 insertions(+), 26 deletions(-)

diff --git a/debian/taler-exchange.install b/debian/taler-exchange.install
index ca77c3d7..0af0788a 100644
--- a/debian/taler-exchange.install
+++ b/debian/taler-exchange.install
@@ -1,7 +1,9 @@
 usr/bin/taler-exchange-aggregator
 usr/bin/taler-exchange-closer
 usr/bin/taler-exchange-dbinit
+usr/bin/taler-exchange-expire
 usr/bin/taler-exchange-httpd
+usr/bin/taler-exchange-router
 usr/bin/taler-exchange-secmod-cs
 usr/bin/taler-exchange-secmod-eddsa
 usr/bin/taler-exchange-secmod-rsa
@@ -11,7 +13,9 @@ usr/bin/taler-exchange-wire-gateway-client
 usr/share/man/man1/taler-exchange-aggregator*
 usr/share/man/man1/taler-exchange-closer*
 usr/share/man/man1/taler-exchange-dbinit*
+usr/share/man/man1/taler-exchange-expire*
 usr/share/man/man1/taler-exchange-httpd*
+usr/share/man/man1/taler-exchange-router*
 usr/share/man/man1/taler-exchange-secmod-eddsa*
 usr/share/man/man1/taler-exchange-secmod-rsa*
 usr/share/man/man1/taler-exchange-secmod-cs*
diff --git a/src/exchange/taler-exchange-expire.c 
b/src/exchange/taler-exchange-expire.c
index c7691930..b5df64a7 100644
--- a/src/exchange/taler-exchange-expire.c
+++ b/src/exchange/taler-exchange-expire.c
@@ -95,6 +95,12 @@ static int global_ret;
  */
 static int test_mode;
 
+/**
+ * If this is a first-time run, we immediately
+ * try to catch up with the present.
+ */
+static bool jump_mode;
+
 
 /**
  * Select a shard to work on.
@@ -188,6 +194,7 @@ static void
 release_shard (struct Shard *s)
 {
   enum GNUNET_DB_QueryStatus qs;
+  unsigned long long wc = (unsigned long long) s->work_counter;
 
   qs = db_plugin->complete_shard (
     db_plugin->cls,
@@ -209,10 +216,14 @@ release_shard (struct Shard *s)
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Purse expiration shard completed with %llu purses\n",
-                (unsigned long long) s->work_counter);
+                wc);
     /* normal case */
     break;
   }
+  if ( (0 == wc) &&
+       (test_mode) &&
+       (! jump_mode) )
+    GNUNET_SCHEDULER_shutdown ();
 }
 
 
@@ -262,13 +273,16 @@ run_expire (void *cls)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Failed to obtain database connection!\n");
+    abort_shard (s);
     global_ret = EXIT_FAILURE;
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  if (db_plugin->start (db_plugin->cls,
+  if (GNUNET_OK !=
+      db_plugin->start (db_plugin->cls,
                         "expire-purse"))
   {
+    GNUNET_break (0);
     global_ret = EXIT_FAILURE;
     db_plugin->rollback (db_plugin->cls);
     abort_shard (s);
@@ -290,6 +304,7 @@ run_expire (void *cls)
   case GNUNET_DB_STATUS_SOFT_ERROR:
     db_plugin->rollback (db_plugin->cls);
     abort_shard (s);
+    GNUNET_assert (NULL == task);
     task = GNUNET_SCHEDULER_add_now (&run_shard,
                                      NULL);
     return;
@@ -303,6 +318,7 @@ run_expire (void *cls)
     {
       release_shard (s);
     }
+    GNUNET_assert (NULL == task);
     task = GNUNET_SCHEDULER_add_now (&run_shard,
                                      NULL);
     return;
@@ -310,6 +326,7 @@ run_expire (void *cls)
     /* commit, and go again immediately */
     s->work_counter++;
     (void) commit_or_warn ();
+    GNUNET_assert (NULL == task);
     task = GNUNET_SCHEDULER_add_now (&run_expire,
                                      s);
   }
@@ -343,9 +360,15 @@ run_shard (void *cls)
   qs = db_plugin->begin_shard (db_plugin->cls,
                                "expire",
                                shard_size,
-                               shard_size.rel_value_us,
+                               jump_mode
+                               ? GNUNET_TIME_absolute_subtract (
+                                 GNUNET_TIME_absolute_get (),
+                                 shard_size).
+                               abs_value_us
+                               : shard_size.rel_value_us,
                                &s->shard_start.abs_value_us,
                                &s->shard_end.abs_value_us);
+  jump_mode = false;
   if (0 >= qs)
   {
     if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
@@ -355,6 +378,7 @@ run_shard (void *cls)
       GNUNET_free (s);
       delay = GNUNET_TIME_randomized_backoff (delay,
                                               GNUNET_TIME_UNIT_SECONDS);
+      GNUNET_assert (NULL == task);
       task = GNUNET_SCHEDULER_add_delayed (delay,
                                            &run_shard,
                                            NULL);
@@ -368,9 +392,10 @@ run_shard (void *cls)
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
-  if (GNUNET_TIME_absolute_is_future (s->shard_end))
+  if (GNUNET_TIME_absolute_is_future (s->shard_start))
   {
-    task = GNUNET_SCHEDULER_add_at (s->shard_end,
+    GNUNET_assert (NULL == task);
+    task = GNUNET_SCHEDULER_add_at (s->shard_start,
                                     &run_shard,
                                     NULL);
     abort_shard (s);
@@ -379,12 +404,12 @@ run_shard (void *cls)
   /* If this is a first-time run, we immediately
      try to catch up with the present */
   if (GNUNET_TIME_absolute_is_zero (s->shard_start))
-    s->shard_end = GNUNET_TIME_absolute_get ();
-
+    jump_mode = true;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "Starting shard [%llu:%llu]!\n",
+              "Starting shard [%llu:%llu)!\n",
               (unsigned long long) s->shard_start.abs_value_us,
               (unsigned long long) s->shard_end.abs_value_us);
+  GNUNET_assert (NULL == task);
   task = GNUNET_SCHEDULER_add_now (&run_expire,
                                    s);
 }
diff --git a/src/exchange/taler-exchange-httpd.h 
b/src/exchange/taler-exchange-httpd.h
index bb387696..278a05be 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -309,8 +309,8 @@ struct TEH_RequestHandler
      * @return MHD result code
      */
     MHD_RESULT
-      (*get)(struct TEH_RequestContext *rc,
-             const char *const args[]);
+    (*get)(struct TEH_RequestContext *rc,
+           const char *const args[]);
 
 
     /**
diff --git a/src/exchange/taler-exchange-httpd_purses_get.c 
b/src/exchange/taler-exchange-httpd_purses_get.c
index 656a34db..12a24489 100644
--- a/src/exchange/taler-exchange-httpd_purses_get.c
+++ b/src/exchange/taler-exchange-httpd_purses_get.c
@@ -333,6 +333,37 @@ TEH_handler_purses_get (struct TEH_RequestContext *rc,
     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
       break; /* handled below */
     }
+    if (GNUNET_TIME_absolute_cmp (gc->timeout,
+                                  >,
+                                  gc->purse_expiration.abs_time))
+    {
+      /* Timeout too high, need to replace event handler */
+      struct TALER_PurseEventP rep = {
+        .header.size = htons (sizeof (rep)),
+        .header.type = htons (
+          gc->wait_for_merge
+        ? TALER_DBEVENT_EXCHANGE_PURSE_MERGED
+        : TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED),
+        .purse_pub = gc->purse_pub
+      };
+      struct GNUNET_DB_EventHandler *eh2;
+
+      gc->timeout = gc->purse_expiration.abs_time;
+      eh2 = TEH_plugin->event_listen (
+        TEH_plugin->cls,
+        GNUNET_TIME_absolute_get_remaining (gc->timeout),
+        &rep.header,
+        &db_event_cb,
+        rc);
+      if (NULL == eh2)
+      {
+        GNUNET_break (0);
+        gc->timeout = GNUNET_TIME_UNIT_ZERO_ABS;
+      }
+      TEH_plugin->event_listen_cancel (TEH_plugin->cls,
+                                       gc->eh);
+      gc->eh = eh2;
+    }
   }
   if (GNUNET_TIME_absolute_is_past (gc->purse_expiration.abs_time))
   {
diff --git a/src/exchangedb/common-0001.sql b/src/exchangedb/common-0001.sql
index 05394246..cb64f446 100644
--- a/src/exchangedb/common-0001.sql
+++ b/src/exchangedb/common-0001.sql
@@ -1193,6 +1193,14 @@ BEGIN
     '(merge_pub);'
   );
 
+  -- FIXME: drop index on master (crosses shards)?
+  -- Or use materialized index? (needed?)
+  EXECUTE FORMAT (
+    'CREATE INDEX IF NOT EXISTS ' || table_name || '_purse_expiration '
+    'ON ' || table_name || ' '
+    '(purse_expiration);'
+  );
+
 END
 $$;
 
diff --git a/src/exchangedb/exchange-0001-part.sql 
b/src/exchangedb/exchange-0001-part.sql
index 97c26cb0..1b1d2a38 100644
--- a/src/exchangedb/exchange-0001-part.sql
+++ b/src/exchangedb/exchange-0001-part.sql
@@ -2505,8 +2505,7 @@ UPDATE known_coins
          THEN 1
          ELSE 0
          END
-  WHERE coin_pub=in_coin_pub
-  LIMIT 1; -- just to be extra safe
+  WHERE coin_pub=in_coin_pub;
 
 
 out_conflict=FALSE;
@@ -3363,7 +3362,6 @@ END $$;
 
 
 CREATE OR REPLACE FUNCTION exchange_do_expire_purse(
-  IN in_partner_id INT8,
   IN in_start_time INT8,
   IN in_end_time INT8,
   OUT out_found BOOLEAN)
@@ -3375,25 +3373,26 @@ DECLARE
   my_deposit record;
 BEGIN
 
-UPDATE purse_requests
- SET refunded=TRUE,
-     finished=TRUE
+SELECT purse_pub
+  INTO my_purse_pub
+  FROM purse_requests
  WHERE (purse_expiration >= in_start_time) AND
        (purse_expiration < in_end_time) AND
        (NOT finished) AND
        (NOT refunded)
- RETURNING purse_pub
-   ,in_reserve_quota
-   ,flags
- INTO my_purse_pub
-   ,my_rq
-   ,my_flags;
+ ORDER BY purse_expiration ASC
+ LIMIT 1;
 out_found = FOUND;
 IF NOT FOUND
 THEN
   RETURN;
 END IF;
 
+UPDATE purse_requests
+ SET refunded=TRUE,
+     finished=TRUE
+ WHERE purse_pub=my_purse_pub;
+
 -- restore balance to each coin deposited into the purse
 FOR my_deposit IN
   SELECT coin_pub
@@ -3402,7 +3401,7 @@ FOR my_deposit IN
     FROM purse_deposits
   WHERE purse_pub = my_purse_pub
 LOOP
-  UPDATE
+  UPDATE known_coins SET
     remaining_frac=remaining_frac+my_deposit.amount_with_fee_frac
      - CASE
        WHEN remaining_frac+my_deposit.amount_with_fee_frac >= 100000000
@@ -3415,9 +3414,7 @@ LOOP
        THEN 1
        ELSE 0
        END
-    FROM known_coins
-    WHERE coin_pub = my_deposit.coin_pub
-    LIMIT 1; -- just to be extra safe
+    WHERE coin_pub = my_deposit.coin_pub;
   END LOOP;
 END $$;
 
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 930a8e9a..b0dee023 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -1211,6 +1211,30 @@ TALER_TESTING_cmd_exec_wirewatch (const char *label,
                                   const char *config_filename);
 
 
+/**
+ * Make a "expire" CMD.
+ *
+ * @param label command label.
+ * @param config_filename configuration filename.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_expire (const char *label,
+                               const char *config_filename);
+
+
+/**
+ * Make a "router" CMD.
+ *
+ * @param label command label.
+ * @param config_filename configuration filename.
+ * @return the command.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_router (const char *label,
+                               const char *config_filename);
+
+
 /**
  * Run a "taler-exchange-aggregator" CMD.
  *
diff --git a/src/lib/exchange_api_purses_get.c 
b/src/lib/exchange_api_purses_get.c
index db511128..021954c2 100644
--- a/src/lib/exchange_api_purses_get.c
+++ b/src/lib/exchange_api_purses_get.c
@@ -169,6 +169,11 @@ handle_purse_get_finished (void *cls,
     /* Exchange does not know about transaction;
        we should pass the reply to the application */
     break;
+  case MHD_HTTP_GONE:
+    /* purse expired */
+    dr.hr.ec = TALER_JSON_get_error_code (j);
+    dr.hr.hint = TALER_JSON_get_error_hint (j);
+    break;
   case MHD_HTTP_INTERNAL_SERVER_ERROR:
     dr.hr.ec = TALER_JSON_get_error_code (j);
     dr.hr.hint = TALER_JSON_get_error_hint (j);
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 4d3c6061..42c4d8d6 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -61,6 +61,8 @@ libtalertesting_la_SOURCES = \
   testing_api_cmd_exec_aggregator.c \
   testing_api_cmd_exec_auditor-offline.c \
   testing_api_cmd_exec_closer.c \
+  testing_api_cmd_exec_expire.c \
+  testing_api_cmd_exec_router.c \
   testing_api_cmd_exec_transfer.c \
   testing_api_cmd_exec_wirewatch.c \
   testing_api_cmd_insert_deposit.c \
diff --git a/src/testing/test_exchange_api-cs.conf 
b/src/testing/test_exchange_api-cs.conf
index 79332d64..20471812 100644
--- a/src/testing/test_exchange_api-cs.conf
+++ b/src/testing/test_exchange_api-cs.conf
@@ -45,6 +45,14 @@ DB = postgres
 # exchange (or the twister) is actually listening.
 BASE_URL = "http://localhost:8081/";
 
+# How big is an individual shard to be processed
+# by taler-exchange-expire (in time).  It may take
+# this much time for an expired purse to be really
+# cleaned up and the coins refunded.
+EXPIRE_SHARD_SIZE = 300 ms
+
+EXPIRE_IDLE_SLEEP_INTERVAL = 1 s
+
 [exchangedb-postgres]
 CONFIG = "postgres:///talercheck"
 
diff --git a/src/testing/test_exchange_api-rsa.conf 
b/src/testing/test_exchange_api-rsa.conf
index 1d445662..be0e4bad 100644
--- a/src/testing/test_exchange_api-rsa.conf
+++ b/src/testing/test_exchange_api-rsa.conf
@@ -45,6 +45,15 @@ DB = postgres
 # exchange (or the twister) is actually listening.
 BASE_URL = "http://localhost:8081/";
 
+# How big is an individual shard to be processed
+# by taler-exchange-expire (in time).  It may take
+# this much time for an expired purse to be really
+# cleaned up and the coins refunded.
+EXPIRE_SHARD_SIZE = 300 ms
+
+EXPIRE_IDLE_SLEEP_INTERVAL = 1 s
+
+
 [exchangedb-postgres]
 CONFIG = "postgres:///talercheck"
 
diff --git a/src/testing/test_exchange_p2p.c b/src/testing/test_exchange_p2p.c
index b3e98daa..ec3c660c 100644
--- a/src/testing/test_exchange_p2p.c
+++ b/src/testing/test_exchange_p2p.c
@@ -277,6 +277,62 @@ run (void *cls,
     TALER_TESTING_cmd_end ()
   };
 
+  struct TALER_TESTING_Command expire[] = {
+    TALER_TESTING_cmd_purse_create_with_reserve (
+      "purse-create-with-reserve-expire",
+      MHD_HTTP_OK,
+      "{\"amount\":\"EUR:1\",\"summary\":\"ice cream\"}",
+      true /* upload contract */,
+      GNUNET_TIME_relative_multiply (
+        GNUNET_TIME_UNIT_SECONDS,
+        1), /* expiration */
+      "create-reserve-1"),
+    TALER_TESTING_cmd_purse_poll (
+      "pull-poll-purse-before-expire",
+      MHD_HTTP_GONE,
+      "purse-create-with-reserve-expire",
+      "EUR:1",
+      false,
+      GNUNET_TIME_UNIT_MINUTES),
+    TALER_TESTING_cmd_purse_create_with_deposit (
+      "purse-with-deposit-expire",
+      MHD_HTTP_OK,
+      "{\"amount\":\"EUR:1\",\"summary\":\"ice cream\"}",
+      true, /* upload contract */
+      GNUNET_TIME_relative_multiply (
+        GNUNET_TIME_UNIT_SECONDS,
+        1), /* expiration */
+      "withdraw-coin-1",
+      "EUR:1.01",
+      NULL),
+    TALER_TESTING_cmd_purse_poll (
+      "push-poll-purse-before-expire",
+      MHD_HTTP_GONE,
+      "purse-with-deposit-expire",
+      "EUR:1",
+      true,
+      GNUNET_TIME_UNIT_MINUTES),
+    TALER_TESTING_cmd_sleep ("sleep",
+                             2 /* seconds */),
+    TALER_TESTING_cmd_exec_expire ("exec-expire",
+                                   config_file),
+    TALER_TESTING_cmd_purse_poll_finish (
+      "push-merge-purse-poll-finish-expire",
+      GNUNET_TIME_relative_multiply (
+        GNUNET_TIME_UNIT_SECONDS,
+        15),
+      "push-poll-purse-before-expire"),
+    TALER_TESTING_cmd_purse_poll_finish (
+      "pull-deposit-purse-poll-expire-finish",
+      GNUNET_TIME_relative_multiply (
+        GNUNET_TIME_UNIT_SECONDS,
+        15),
+      "pull-poll-purse-before-expire"),
+    // FIXME: check coin was refunded
+    // FIXME: check reserve purse capacity is back up!
+    TALER_TESTING_cmd_end ()
+  };
+
   struct TALER_TESTING_Command commands[] = {
     /* setup exchange */
     TALER_TESTING_cmd_auditor_add ("add-auditor-OK",
@@ -313,6 +369,8 @@ run (void *cls,
                              push),
     TALER_TESTING_cmd_batch ("pull",
                              pull),
+    TALER_TESTING_cmd_batch ("expire",
+                             expire),
     /* End the suite. */
     TALER_TESTING_cmd_end ()
   };
diff --git a/src/testing/testing_api_cmd_exec_expire.c 
b/src/testing/testing_api_cmd_exec_expire.c
new file mode 100644
index 00000000..aabf3736
--- /dev/null
+++ b/src/testing/testing_api_cmd_exec_expire.c
@@ -0,0 +1,162 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2022 Taler Systems SA
+
+  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.
+
+  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 TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file testing/testing_api_cmd_exec_expire.c
+ * @brief run the taler-exchange-expire command
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+
+
+/**
+ * State for a "expire" CMD.
+ */
+struct ExpireState
+{
+
+  /**
+   * Process for the expireer.
+   */
+  struct GNUNET_OS_Process *expire_proc;
+
+  /**
+   * Configuration file used by the expireer.
+   */
+  const char *config_filename;
+};
+
+
+/**
+ * Run the command; use the `taler-exchange-expire' program.
+ *
+ * @param cls closure.
+ * @param cmd command currently being executed.
+ * @param is interpreter state.
+ */
+static void
+expire_run (void *cls,
+            const struct TALER_TESTING_Command *cmd,
+            struct TALER_TESTING_Interpreter *is)
+{
+  struct ExpireState *ws = cls;
+
+  (void) cmd;
+  ws->expire_proc
+    = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
+                               NULL, NULL, NULL,
+                               "taler-exchange-expire",
+                               "taler-exchange-expire",
+                               "-L", "INFO",
+                               "-c", ws->config_filename,
+                               "-t", /* exit when done */
+                               NULL);
+  if (NULL == ws->expire_proc)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  TALER_TESTING_wait_for_sigchld (is);
+}
+
+
+/**
+ * Free the state of a "expire" CMD, and possibly
+ * kills its process if it did not terminate regularly.
+ *
+ * @param cls closure.
+ * @param cmd the command being freed.
+ */
+static void
+expire_cleanup (void *cls,
+                const struct TALER_TESTING_Command *cmd)
+{
+  struct ExpireState *ws = cls;
+
+  (void) cmd;
+  if (NULL != ws->expire_proc)
+  {
+    GNUNET_break (0 ==
+                  GNUNET_OS_process_kill (ws->expire_proc,
+                                          SIGKILL));
+    GNUNET_OS_process_wait (ws->expire_proc);
+    GNUNET_OS_process_destroy (ws->expire_proc);
+    ws->expire_proc = NULL;
+  }
+  GNUNET_free (ws);
+}
+
+
+/**
+ * Offer "expire" CMD internal data to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static enum GNUNET_GenericReturnValue
+expire_traits (void *cls,
+               const void **ret,
+               const char *trait,
+               unsigned int index)
+{
+  struct ExpireState *ws = cls;
+  struct TALER_TESTING_Trait traits[] = {
+    TALER_TESTING_make_trait_process (&ws->expire_proc),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait (traits,
+                                  ret,
+                                  trait,
+                                  index);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_expire (const char *label,
+                               const char *config_filename)
+{
+  struct ExpireState *ws;
+
+  ws = GNUNET_new (struct ExpireState);
+  ws->config_filename = config_filename;
+
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ws,
+      .label = label,
+      .run = &expire_run,
+      .cleanup = &expire_cleanup,
+      .traits = &expire_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_exec_expire.c */
diff --git a/src/testing/testing_api_cmd_exec_router.c 
b/src/testing/testing_api_cmd_exec_router.c
new file mode 100644
index 00000000..d7f3fe26
--- /dev/null
+++ b/src/testing/testing_api_cmd_exec_router.c
@@ -0,0 +1,161 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2022 Taler Systems SA
+
+  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.
+
+  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 TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file testing/testing_api_cmd_exec_router.c
+ * @brief run the taler-exchange-router command
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include "taler_json_lib.h"
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_signatures.h"
+#include "taler_testing_lib.h"
+
+
+/**
+ * State for a "router" CMD.
+ */
+struct RouterState
+{
+
+  /**
+   * Process for the routerer.
+   */
+  struct GNUNET_OS_Process *router_proc;
+
+  /**
+   * Configuration file used by the routerer.
+   */
+  const char *config_filename;
+};
+
+
+/**
+ * Run the command; use the `taler-exchange-router' program.
+ *
+ * @param cls closure.
+ * @param cmd command currently being executed.
+ * @param is interpreter state.
+ */
+static void
+router_run (void *cls,
+            const struct TALER_TESTING_Command *cmd,
+            struct TALER_TESTING_Interpreter *is)
+{
+  struct RouterState *ws = cls;
+
+  (void) cmd;
+  ws->router_proc
+    = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ALL,
+                               NULL, NULL, NULL,
+                               "taler-exchange-router",
+                               "taler-exchange-router",
+                               "-c", ws->config_filename,
+                               "-t", /* exit when done */
+                               NULL);
+  if (NULL == ws->router_proc)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (is);
+    return;
+  }
+  TALER_TESTING_wait_for_sigchld (is);
+}
+
+
+/**
+ * Free the state of a "router" CMD, and possibly
+ * kills its process if it did not terminate regularly.
+ *
+ * @param cls closure.
+ * @param cmd the command being freed.
+ */
+static void
+router_cleanup (void *cls,
+                const struct TALER_TESTING_Command *cmd)
+{
+  struct RouterState *ws = cls;
+
+  (void) cmd;
+  if (NULL != ws->router_proc)
+  {
+    GNUNET_break (0 ==
+                  GNUNET_OS_process_kill (ws->router_proc,
+                                          SIGKILL));
+    GNUNET_OS_process_wait (ws->router_proc);
+    GNUNET_OS_process_destroy (ws->router_proc);
+    ws->router_proc = NULL;
+  }
+  GNUNET_free (ws);
+}
+
+
+/**
+ * Offer "router" CMD internal data to other commands.
+ *
+ * @param cls closure.
+ * @param[out] ret result.
+ * @param trait name of the trait.
+ * @param index index number of the object to offer.
+ * @return #GNUNET_OK on success.
+ */
+static enum GNUNET_GenericReturnValue
+router_traits (void *cls,
+               const void **ret,
+               const char *trait,
+               unsigned int index)
+{
+  struct RouterState *ws = cls;
+  struct TALER_TESTING_Trait traits[] = {
+    TALER_TESTING_make_trait_process (&ws->router_proc),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait (traits,
+                                  ret,
+                                  trait,
+                                  index);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_exec_router (const char *label,
+                               const char *config_filename)
+{
+  struct RouterState *ws;
+
+  ws = GNUNET_new (struct RouterState);
+  ws->config_filename = config_filename;
+
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = ws,
+      .label = label,
+      .run = &router_run,
+      .cleanup = &router_cleanup,
+      .traits = &router_traits
+    };
+
+    return cmd;
+  }
+}
+
+
+/* end of testing_api_cmd_exec_router.c */
diff --git a/src/testing/testing_api_cmd_purse_get.c 
b/src/testing/testing_api_cmd_purse_get.c
index 3fc57691..61873721 100644
--- a/src/testing/testing_api_cmd_purse_get.c
+++ b/src/testing/testing_api_cmd_purse_get.c
@@ -261,6 +261,7 @@ TALER_TESTING_cmd_purse_poll (
   ss->expected_balance = expected_balance;
   ss->expected_response_code = expected_http_status;
   ss->timeout = timeout;
+  ss->wait_for_merge = wait_for_merge;
   {
     struct TALER_TESTING_Command cmd = {
       .cls = ss,

-- 
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]