gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant] branch master updated: implementing long-polling test c


From: gnunet
Subject: [taler-merchant] branch master updated: implementing long-polling test commands for wallet get order operation (#6466)
Date: Wed, 14 Oct 2020 23:02:05 +0200

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

grothoff pushed a commit to branch master
in repository merchant.

The following commit(s) were added to refs/heads/master by this push:
     new e98ca0d  implementing long-polling test commands for wallet get order 
operation (#6466)
e98ca0d is described below

commit e98ca0d39480b9cb23f7d0f620d9ca10d9afa7aa
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Oct 14 23:02:02 2020 +0200

    implementing long-polling test commands for wallet get order operation 
(#6466)
---
 src/backend/taler-merchant-httpd_get-orders-ID.c |   8 +-
 src/include/taler_merchant_service.h             |   6 +-
 src/include/taler_merchant_testing_lib.h         |  37 +-
 src/testing/testing_api_cmd_merchant_get_order.c |  20 +-
 src/testing/testing_api_cmd_wallet_get_order.c   | 444 ++++++++++++++++++++++-
 5 files changed, 492 insertions(+), 23 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c 
b/src/backend/taler-merchant-httpd_get-orders-ID.c
index 42e5620..82404f6 100644
--- a/src/backend/taler-merchant-httpd_get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -114,14 +114,14 @@ struct GetOrderData
   struct TALER_Amount refund_amount;
 
   /**
-   * Did we suspend @a connection?
+   * Return code: #TALER_EC_NONE if successful.
    */
-  bool suspended;
+  enum TALER_ErrorCode ec;
 
   /**
-   * Return code: #TALER_EC_NONE if successful.
+   * Did we suspend @a connection?
    */
-  enum TALER_ErrorCode ec;
+  bool suspended;
 
   /**
    * Set to true if we are dealing with an unclaimed order
diff --git a/src/include/taler_merchant_service.h 
b/src/include/taler_merchant_service.h
index e34226a..cd16cac 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -1466,7 +1466,7 @@ struct TALER_MERCHANT_OrderWalletGetHandle;
 
 
 /**
- * Callback to process a GET /orders/$ID request
+ * Callback to process a GET /orders/$ID response
  *
  * @param cls closure
  * @param hr HTTP response details
@@ -1509,7 +1509,7 @@ typedef void
  * @param timeout timeout to use in long polling (how long may the server wait 
to reply
  *        before generating an unpaid response). Note that this is just 
provided to
  *        the server, we as client will block until the response comes back or 
until
- *        #TALER_MERCHANT_order_get_cancel() is called.
+ *        #TALER_MERCHANT_wallet_order_get_cancel() is called.
  * @param session_id for which session should the payment status be checked. 
Use
  *        NULL to disregard sessions.
  * @param min_refund long poll for the service to approve a refund exceeding 
this value;
@@ -1825,7 +1825,7 @@ typedef void
  * @param timeout timeout to use in long polling (how long may the server wait 
to reply
  *        before generating an unpaid response). Note that this is just 
provided to
  *        the server, we as client will block until the response comes back or 
until
- *        #TALER_MERCHANT_order_get_cancel() is called.
+ *        #TALER_MERCHANT_merchant_order_get_cancel() is called.
  * @param cb callback which will work the response gotten from the backend
  * @param cb_cls closure to pass to @a cb
  * @return handle for this operation, NULL upon errors
diff --git a/src/include/taler_merchant_testing_lib.h 
b/src/include/taler_merchant_testing_lib.h
index ac50076..8b53c32 100644
--- a/src/include/taler_merchant_testing_lib.h
+++ b/src/include/taler_merchant_testing_lib.h
@@ -575,6 +575,13 @@ TALER_TESTING_cmd_merchant_get_orders (const char *label,
 
 /**
  * Start a long poll for GET /private/orders.
+ *
+ * FIXME: needs additional arguments to specify range to long poll for!
+ *
+ * @param label the command label
+ * @param merchant_url base URL of the merchant which will
+ *        serve the request.
+ * @param timeout how long to wait for the request to complete
  */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_poll_orders_start (const char *label,
@@ -584,6 +591,10 @@ TALER_TESTING_cmd_poll_orders_start (const char *label,
 
 /**
  * Complete a long poll for GET /private/orders.
+ *
+ * @param label the command label
+ * @param http_status expected HTTP response code
+ * @param poll_start_reference reference to the 
#TALER_TESTING_cmd_poll_orders_start command
  */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_poll_orders_conclude (const char *label,
@@ -614,23 +625,39 @@ TALER_TESTING_cmd_wallet_get_order (const char *label,
 
 
 /**
- * Start a long poll for GET /private/orders/$ORDER_ID.
+ * Start a long poll for GET /orders/$ORDER_ID.
+ *
+ * @param label the command label
+ * @param merchant_url base URL of the merchant which will
+ *        serve the request.
+ * @param order_ref reference to a command that created an order.
+ * @param timeout how long to wait for the request to complete
+ * @param await_refund NULL to not wait for refund, amount of value
+ *         zero to wait for any refund amount, non-zero to poll
+ *         for refund exceeding the given amount
  */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_wallet_poll_order_start (
   const char *label,
   const char *merchant_url,
-  const char *order_id,
-  struct GNUNET_TIME_Relative timeout);
+  const char *order_ref,
+  struct GNUNET_TIME_Relative timeout,
+  const struct TALER_Amount *await_refund);
 
 
 /**
- * Complete a long poll for GET /private/orders/$ORDER_ID.
+ * Complete a long poll for GET /orders/$ORDER_ID.
+ *
+ * @param label the command label
+ * @param expected_http_status expected HTTP response code
+ * @param expected_refund_amount refund expected, NULL for no refund expected
+ * @param poll_start_reference reference to the 
#TALER_TESTING_cmd_wallet_poll_order_start command
  */
 struct TALER_TESTING_Command
 TALER_TESTING_cmd_wallet_poll_order_conclude (
   const char *label,
-  unsigned int http_status,
+  unsigned int expected_http_status,
+  const char *expected_refund_amount,
   const char *poll_start_reference);
 
 
diff --git a/src/testing/testing_api_cmd_merchant_get_order.c 
b/src/testing/testing_api_cmd_merchant_get_order.c
index 241562e..002442a 100644
--- a/src/testing/testing_api_cmd_merchant_get_order.c
+++ b/src/testing/testing_api_cmd_merchant_get_order.c
@@ -63,11 +63,6 @@ struct MerchantGetOrderState
    */
   enum TALER_MERCHANT_OrderStatusCode osc;
 
-  /**
-   * Whether the order was refunded or not.
-   */
-  bool refunded;
-
   /**
    * A NULL-terminated list of refunds associated with this order.
    */
@@ -78,11 +73,6 @@ struct MerchantGetOrderState
    */
   unsigned int refunds_length;
 
-  /**
-   * Whether the order was wired or not.
-   */
-  bool wired;
-
   /**
    * A NULL-terminated list of transfers associated with this order.
    */
@@ -102,6 +92,16 @@ struct MerchantGetOrderState
    * The length of @e forgets.
    */
   unsigned int forgets_length;
+
+  /**
+   * Whether the order was refunded or not.
+   */
+  bool refunded;
+
+  /**
+   * Whether the order was wired or not.
+   */
+  bool wired;
 };
 
 
diff --git a/src/testing/testing_api_cmd_wallet_get_order.c 
b/src/testing/testing_api_cmd_wallet_get_order.c
index d667f10..56ff474 100644
--- a/src/testing/testing_api_cmd_wallet_get_order.c
+++ b/src/testing/testing_api_cmd_wallet_get_order.c
@@ -149,7 +149,7 @@ wallet_get_order_cb (
       TALER_TESTING_interpreter_fail (gos->is);
       return;
     }
-    if (!paid_b)
+    if (! paid_b)
     {
       /* FIXME: Check all of the members of `pud` */
       struct TALER_MERCHANT_PayUriData pud;
@@ -331,4 +331,446 @@ TALER_TESTING_cmd_wallet_get_order (const char *label,
 }
 
 
+struct WalletPollOrderConcludeState
+{
+  /**
+   * The interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Reference to a command that can provide a poll order start command.
+   */
+  const char *start_reference;
+
+  /**
+   * Task to wait for the deadline.
+   */
+  struct GNUNET_SCHEDULER_Task *task;
+
+  /**
+   * Amount of a refund expected.
+   */
+  struct TALER_Amount expected_refund_amount;
+
+  /**
+   * Expected HTTP response status code.
+   */
+  unsigned int expected_http_status;
+
+  /**
+   * Are we expecting a refund?
+   */
+  bool expected_refund;
+};
+
+
+struct WalletPollOrderStartState
+{
+  /**
+   * The merchant base URL.
+   */
+  const char *merchant_url;
+
+  /**
+   * The handle to the current GET /orders/$ORDER_ID request.
+   */
+  struct TALER_MERCHANT_OrderWalletGetHandle *ogh;
+
+  /**
+   * The interpreter state.
+   */
+  struct TALER_TESTING_Interpreter *is;
+
+  /**
+   * Reference to a command that created an order.
+   */
+  const char *order_ref;
+
+  /**
+   * How long to wait for server to return a response.
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * Conclude state waiting for completion (if any).
+   */
+  struct WalletPollOrderConcludeState *cs;
+
+  /**
+   * The HTTP status code returned by the backend.
+   */
+  unsigned int http_status;
+
+  /**
+   * When the request should be completed by.
+   */
+  struct GNUNET_TIME_Absolute deadline;
+
+  /**
+   * Minimum refund to wait for.
+   */
+  struct TALER_Amount refund_threshold;
+
+  /**
+   * Available refund as returned by the merchant.
+   */
+  struct TALER_Amount refund_available;
+
+  /**
+   * Should we poll for a refund?
+   */
+  bool wait_for_refund;
+
+  /**
+   * Did we receive a refund according to response from the merchant?
+   */
+  bool refunded;
+
+  /**
+   * Was the order paid according to response from the merchant?
+   */
+  bool paid;
+
+  /**
+   * Has the order a pending refund according to response from the merchant?
+   */
+  bool refund_pending;
+};
+
+
+/**
+ * Task called when either the timeout for the GET /private/order/<ID> command
+ * expired or we got a response.  Checks if the result is what we expected.
+ *
+ * @param cls a `struct WalletPollOrderConcludeState`
+ */
+static void
+conclude_task (void *cls)
+{
+  struct WalletPollOrderConcludeState *ppc = cls;
+  const struct TALER_TESTING_Command *poll_cmd;
+  struct WalletPollOrderStartState *cps;
+  struct GNUNET_TIME_Absolute now;
+
+  ppc->task = NULL;
+  poll_cmd =
+    TALER_TESTING_interpreter_lookup_command (ppc->is,
+                                              ppc->start_reference);
+  if (NULL == poll_cmd)
+    TALER_TESTING_FAIL (ppc->is);
+  cps = poll_cmd->cls;
+  if (NULL != cps->ogh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected poll GET /orders/$ORDER_ID to have completed, but it 
did not!\n");
+    TALER_TESTING_FAIL (ppc->is);
+  }
+  if (cps->http_status != ppc->expected_http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected HTTP status %u, got %u\n",
+                ppc->expected_http_status,
+                cps->http_status);
+    TALER_TESTING_FAIL (ppc->is);
+  }
+  if (ppc->expected_refund != cps->refunded)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Order was %srefunded, contrary to our expectations\n",
+                cps->refunded ? "" : "NOT ");
+    TALER_TESTING_FAIL (ppc->is);
+  }
+  if (cps->refunded)
+  {
+    if (0 != TALER_amount_cmp (&ppc->expected_refund_amount,
+                               &cps->refund_available))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Refund amount %s does not match our expectation!\n",
+                  TALER_amount2s (&cps->refund_available));
+      TALER_TESTING_FAIL (ppc->is);
+    }
+  }
+  // FIXME: add checks for cps->paid/refund_available status flags?
+  now = GNUNET_TIME_absolute_get ();
+  if ((GNUNET_TIME_absolute_add (cps->deadline,
+                                 GNUNET_TIME_UNIT_SECONDS).abs_value_us <
+       now.abs_value_us) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected answer to be delayed until %llu, but got response at 
%llu\n",
+                (unsigned long long) cps->deadline.abs_value_us,
+                (unsigned long long) now.abs_value_us);
+    TALER_TESTING_FAIL (ppc->is);
+  }
+  TALER_TESTING_interpreter_next (ppc->is);
+}
+
+
+/**
+ * Process response from a GET /orders/$ID request
+ *
+ * @param cls a `struct WalletPollOrderStartState *`
+ * @param hr HTTP response details
+ * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
+ *        settled, #GNUNET_SYSERR on error
+ *        (note that refunded payments are returned as paid!)
+ * @param refunded #GNUNET_YES if there is at least on refund on this payment,
+ *        #GNUNET_NO if refunded, #GNUNET_SYSERR or error
+ * @param refund_pending #GNUNET_YES if there are refunds waiting to be
+ *        obtained, #GNUNET_NO if all refunds have been obtained, 
#GNUNET_SYSERR
+ *        on error.
+ * @param refunded_amount amount that was refunded, NULL if there
+ *        was no refund
+ * @param taler_pay_uri the URI that instructs the wallets to process
+ *                      the payment
+ * @param already_paid_order_id equivalent order that this customer
+ *                      paid already, or NULL for none
+ */
+static void
+wallet_poll_order_cb (
+  void *cls,
+  const struct TALER_MERCHANT_HttpResponse *hr,
+  enum GNUNET_GenericReturnValue paid,
+  enum GNUNET_GenericReturnValue refunded,
+  enum GNUNET_GenericReturnValue refund_pending,
+  struct TALER_Amount *refund_amount,
+  const char *taler_pay_uri,
+  const char *already_paid_order_id)
+{
+  struct WalletPollOrderStartState *pos = cls;
+
+  pos->ogh = NULL;
+  pos->http_status = hr->http_status;
+  switch (hr->http_status)
+  {
+  case MHD_HTTP_OK:
+    pos->paid = (GNUNET_YES == paid);
+    pos->refunded = (GNUNET_YES == refunded);
+    pos->refund_pending = (GNUNET_YES == refund_pending);
+    if (NULL != refund_amount)
+      pos->refund_available = *refund_amount;
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Unhandled HTTP status.\n");
+    break;
+  }
+  if (NULL != pos->cs)
+  {
+    GNUNET_SCHEDULER_cancel (pos->cs->task);
+    pos->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task,
+                                              pos->cs);
+  }
+}
+
+
+/**
+ * Run the "GET order" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command being run now.
+ * @param is interpreter state.
+ */
+static void
+wallet_poll_order_start_run (void *cls,
+                             const struct TALER_TESTING_Command *cmd,
+                             struct TALER_TESTING_Interpreter *is)
+{
+  struct WalletPollOrderStartState *pos = cls;
+  const struct TALER_TESTING_Command *order_cmd;
+  const char *order_id;
+  const struct GNUNET_HashCode *h_contract;
+
+  order_cmd = TALER_TESTING_interpreter_lookup_command (
+    is,
+    pos->order_ref);
+
+  if (GNUNET_OK !=
+      TALER_TESTING_get_trait_order_id (order_cmd,
+                                        0,
+                                        &order_id))
+    TALER_TESTING_FAIL (is);
+
+  if (GNUNET_OK !=
+      TALER_TESTING_get_trait_h_contract_terms (order_cmd,
+                                                0,
+                                                &h_contract))
+    TALER_TESTING_FAIL (is);
+
+  /* add 1s grace time to timeout */
+  pos->deadline
+    = GNUNET_TIME_absolute_add (GNUNET_TIME_relative_to_absolute 
(pos->timeout),
+                                GNUNET_TIME_UNIT_SECONDS);
+  pos->is = is;
+  pos->ogh = TALER_MERCHANT_wallet_order_get (is->ctx,
+                                              pos->merchant_url,
+                                              order_id,
+                                              h_contract,
+                                              pos->timeout,
+                                              NULL,
+                                              pos->wait_for_refund
+                                              ? &pos->refund_threshold
+                                              : NULL,
+                                              pos->wait_for_refund,
+                                              &wallet_poll_order_cb,
+                                              pos);
+  GNUNET_assert (NULL != pos->ogh);
+  /* We CONTINUE to run the interpreter while the long-polled command
+     completes asynchronously! */
+  TALER_TESTING_interpreter_next (pos->is);
+}
+
+
+/**
+ * Free the state of a "GET order" CMD, and possibly
+ * cancel a pending operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd command being run.
+ */
+static void
+wallet_poll_order_start_cleanup (void *cls,
+                                 const struct TALER_TESTING_Command *cmd)
+{
+  struct WalletPollOrderStartState *pos = cls;
+
+  if (NULL != pos->ogh)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Command `%s' was not terminated\n",
+                TALER_TESTING_interpreter_get_current_label (
+                  pos->is));
+    TALER_MERCHANT_wallet_order_get_cancel (pos->ogh);
+  }
+  GNUNET_free (pos);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wallet_poll_order_start (
+  const char *label,
+  const char *merchant_url,
+  const char *order_ref,
+  struct GNUNET_TIME_Relative timeout,
+  const struct TALER_Amount *await_refund)
+{
+  struct WalletPollOrderStartState *pos;
+
+  pos = GNUNET_new (struct WalletPollOrderStartState);
+  pos->order_ref = order_ref;
+  pos->merchant_url = merchant_url;
+  pos->timeout = timeout;
+  if (NULL != await_refund)
+  {
+    pos->wait_for_refund = true;
+    pos->refund_threshold = *await_refund;
+  }
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = pos,
+      .label = label,
+      .run = &wallet_poll_order_start_run,
+      .cleanup = &wallet_poll_order_start_cleanup
+    };
+
+    return cmd;
+  }
+}
+
+
+/**
+ * Run the "GET order conclude" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command being run now.
+ * @param is interpreter state.
+ */
+static void
+wallet_poll_order_conclude_run (void *cls,
+                                const struct TALER_TESTING_Command *cmd,
+                                struct TALER_TESTING_Interpreter *is)
+{
+  struct WalletPollOrderConcludeState *poc = cls;
+  const struct TALER_TESTING_Command *poll_cmd;
+  struct WalletPollOrderStartState *pos;
+
+  poc->is = is;
+  poll_cmd =
+    TALER_TESTING_interpreter_lookup_command (is,
+                                              poc->start_reference);
+  if (NULL == poll_cmd)
+    TALER_TESTING_FAIL (poc->is);
+  GNUNET_assert (poll_cmd->run == &wallet_poll_order_start_run);
+  pos = poll_cmd->cls;
+  pos->cs = poc;
+  if (NULL == pos->ogh)
+    poc->task = GNUNET_SCHEDULER_add_now (&conclude_task,
+                                          poc);
+  else
+    poc->task = GNUNET_SCHEDULER_add_at (pos->deadline,
+                                         &conclude_task,
+                                         poc);
+}
+
+
+/**
+ * Free the state of a "GET order" CMD, and possibly
+ * cancel a pending operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd command being run.
+ */
+static void
+wallet_poll_order_conclude_cleanup (void *cls,
+                                    const struct TALER_TESTING_Command *cmd)
+{
+  struct WalletPollOrderConcludeState *poc = cls;
+
+  if (NULL != poc->task)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Command `%s' was not terminated\n",
+                TALER_TESTING_interpreter_get_current_label (
+                  poc->is));
+    GNUNET_SCHEDULER_cancel (poc->task);
+    poc->task = NULL;
+  }
+  GNUNET_free (poc);
+}
+
+
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_wallet_poll_order_conclude (
+  const char *label,
+  unsigned int expected_http_status,
+  const char *expected_refund_amount,
+  const char *poll_start_reference)
+{
+  struct WalletPollOrderConcludeState *cps;
+
+  cps = GNUNET_new (struct WalletPollOrderConcludeState);
+  cps->start_reference = poll_start_reference;
+  cps->expected_http_status = expected_http_status;
+  if (NULL != expected_refund_amount)
+  {
+    cps->expected_refund = true;
+    GNUNET_assert (GNUNET_OK ==
+                   TALER_string_to_amount (expected_refund_amount,
+                                           &cps->expected_refund_amount));
+  }
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = cps,
+      .label = label,
+      .run = &wallet_poll_order_conclude_run,
+      .cleanup = &wallet_poll_order_conclude_cleanup
+    };
+
+    return cmd;
+  }
+}
+
+
 /* end of testing_api_cmd_wallet_get_order.c */

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