aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_get_orders.c
diff options
context:
space:
mode:
authorJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-06-29 13:48:40 -0400
committerJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-06-29 13:48:40 -0400
commitb637514b36e6c0f44505fca510f3033b85c932ff (patch)
tree4e6487c244efd1818221a6afe010465bb0c6906a /src/testing/testing_api_cmd_get_orders.c
parenta118bd2c4951fa7b60737e3cca69e62266a1bcef (diff)
long polling test for GET /private/orders
Diffstat (limited to 'src/testing/testing_api_cmd_get_orders.c')
-rw-r--r--src/testing/testing_api_cmd_get_orders.c337
1 files changed, 337 insertions, 0 deletions
diff --git a/src/testing/testing_api_cmd_get_orders.c b/src/testing/testing_api_cmd_get_orders.c
index d4073b04..db3e20a2 100644
--- a/src/testing/testing_api_cmd_get_orders.c
+++ b/src/testing/testing_api_cmd_get_orders.c
@@ -236,4 +236,341 @@ TALER_TESTING_cmd_merchant_get_orders (const char *label,
}
+struct MerchantPollOrdersConcludeState
+{
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Reference to a command that can provide a poll orders start command.
+ */
+ const char *start_reference;
+
+ /**
+ * Task to wait for the deadline.
+ */
+ struct GNUNET_SCHEDULER_Task *task;
+
+ /**
+ * Expected HTTP response status code.
+ */
+ unsigned int expected_http_status;
+};
+
+
+struct MerchantPollOrdersStartState
+{
+ /**
+ * The merchant base URL.
+ */
+ const char *merchant_url;
+
+ /**
+ * The handle to the current GET /private/orders request.
+ */
+ struct TALER_MERCHANT_OrdersGetHandle *ogh;
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * How long to wait for server to return a response.
+ */
+ struct GNUNET_TIME_Relative timeout;
+
+ /**
+ * Conclude state waiting for completion (if any).
+ */
+ struct MerchantPollOrdersConcludeState *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;
+};
+
+
+/**
+ * Task called when either the timeout for the get orders
+ * command expired or we got a response. Checks if the
+ * result is what we expected.
+ *
+ * @param cls a `struct MerchantPollOrdersConcludeState`
+ */
+static void
+conclude_task (void *cls)
+{
+ struct MerchantPollOrdersConcludeState *poc = cls;
+ const struct TALER_TESTING_Command *poll_cmd;
+ struct MerchantPollOrdersStartState *pos;
+ struct GNUNET_TIME_Absolute now;
+
+ poc->task = NULL;
+ poll_cmd =
+ TALER_TESTING_interpreter_lookup_command (poc->is,
+ poc->start_reference);
+ if (NULL == poll_cmd)
+ TALER_TESTING_FAIL (poc->is);
+ pos = poll_cmd->cls;
+ if (NULL != pos->ogh)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected poll GET /private/orders to have completed, but it did not!\n");
+ TALER_TESTING_FAIL (poc->is);
+ }
+ if (pos->http_status != poc->expected_http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected HTTP status %u, got %u\n",
+ poc->expected_http_status,
+ pos->http_status);
+ TALER_TESTING_FAIL (poc->is);
+ }
+ now = GNUNET_TIME_absolute_get ();
+ if ((GNUNET_TIME_absolute_add (pos->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) pos->deadline.abs_value_us,
+ (unsigned long long) now.abs_value_us);
+ TALER_TESTING_FAIL (poc->is);
+ }
+ TALER_TESTING_interpreter_next (poc->is);
+}
+
+
+/**
+ * Callback to process a GET /orders request
+ *
+ * @param cls closure
+ * @param hr HTTP response details
+ * @param osr order status response details (on success)
+ */
+static void
+merchant_poll_orders_cb (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ unsigned int orders_length,
+ const struct TALER_MERCHANT_OrderEntry orders[])
+{
+ /* FIXME, deeper checks should be implemented here. */
+ struct MerchantPollOrdersStartState *pos = cls;
+
+ pos->ogh = NULL;
+ if (MHD_HTTP_OK != hr->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u (%d) to command %s\n",
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (pos->is));
+ TALER_TESTING_interpreter_fail (pos->is);
+ return;
+ }
+ switch (hr->http_status)
+ {
+ case MHD_HTTP_OK:
+ // FIXME: use order references
+ // check if the data returned matches that from the POST / PATCH
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Unhandled HTTP status.\n");
+ }
+ pos->http_status = hr->http_status;
+ if (NULL != pos->cs)
+ {
+ GNUNET_SCHEDULER_cancel (pos->cs->task);
+ pos->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task,
+ pos->cs);
+ }
+}
+
+
+/**
+ * Run the "GET orders" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command being run now.
+ * @param is interpreter state.
+ */
+static void
+merchant_poll_orders_start_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct MerchantPollOrdersStartState *pos = cls;
+
+ /* 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_orders_get2 (is->ctx,
+ pos->merchant_url,
+ TALER_EXCHANGE_YNA_ALL,
+ TALER_EXCHANGE_YNA_ALL,
+ TALER_EXCHANGE_YNA_ALL,
+ GNUNET_TIME_UNIT_ZERO_ABS,
+ 1,
+ 2,
+ pos->timeout,
+ &merchant_poll_orders_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 orders" CMD, and possibly
+ * cancel a pending operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd command being run.
+ */
+static void
+merchant_poll_orders_start_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct MerchantPollOrdersStartState *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_orders_get_cancel (pos->ogh);
+ }
+ GNUNET_free (pos);
+}
+
+
+/**
+ * Start a long poll for GET /private/orders.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_poll_orders_start (const char *label,
+ const char *merchant_url,
+ struct GNUNET_TIME_Relative timeout)
+{
+ struct MerchantPollOrdersStartState *pos;
+
+ pos = GNUNET_new (struct MerchantPollOrdersStartState);
+ pos->merchant_url = merchant_url;
+ pos->timeout = timeout;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = pos,
+ .label = label,
+ .run = &merchant_poll_orders_start_run,
+ .cleanup = &merchant_poll_orders_start_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
+/**
+ * Run the "GET orders" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command being run now.
+ * @param is interpreter state.
+ */
+static void
+merchant_poll_orders_conclude_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct MerchantPollOrdersConcludeState *poc = cls;
+ const struct TALER_TESTING_Command *poll_cmd;
+ struct MerchantPollOrdersStartState *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 == &merchant_poll_orders_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 orders" CMD, and possibly
+ * cancel a pending operation thereof.
+ *
+ * @param cls closure.
+ * @param cmd command being run.
+ */
+static void
+merchant_poll_orders_conclude_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct MerchantPollOrdersConcludeState *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);
+}
+
+
+/**
+ * Complete a long poll for GET /private/orders.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_poll_orders_conclude (const char *label,
+ unsigned int http_status,
+ const char *poll_start_reference)
+{
+ struct MerchantPollOrdersConcludeState *poc;
+
+ poc = GNUNET_new (struct MerchantPollOrdersConcludeState);
+ poc->start_reference = poll_start_reference;
+ poc->expected_http_status = http_status;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = poc,
+ .label = label,
+ .run = &merchant_poll_orders_conclude_run,
+ .cleanup = &merchant_poll_orders_conclude_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
/* end of testing_api_cmd_get_orders.c */