summaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_merchant_get_order.c
diff options
context:
space:
mode:
authorJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-06-26 23:58:55 -0400
committerJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-06-26 23:58:55 -0400
commitcde317f8e848c61e399c6c3e93264b1736f33e74 (patch)
treee5efe98d771cf14174ccc31ef5bc6a044ac8e414 /src/testing/testing_api_cmd_merchant_get_order.c
parentab27991b9a8cf9618891ce74e2d86f8b1a916365 (diff)
downloadmerchant-cde317f8e848c61e399c6c3e93264b1736f33e74.tar.gz
merchant-cde317f8e848c61e399c6c3e93264b1736f33e74.tar.bz2
merchant-cde317f8e848c61e399c6c3e93264b1736f33e74.zip
more docs/thorough checks for backend db & long polling for merchant get order
Diffstat (limited to 'src/testing/testing_api_cmd_merchant_get_order.c')
-rw-r--r--src/testing/testing_api_cmd_merchant_get_order.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/src/testing/testing_api_cmd_merchant_get_order.c b/src/testing/testing_api_cmd_merchant_get_order.c
index f3070392..76bc75b8 100644
--- a/src/testing/testing_api_cmd_merchant_get_order.c
+++ b/src/testing/testing_api_cmd_merchant_get_order.c
@@ -366,4 +366,344 @@ TALER_TESTING_cmd_merchant_get_order (const char *label,
}
+struct MerchantPollOrderConcludeState
+{
+ /**
+ * 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;
+
+ /**
+ * Expected HTTP response status code.
+ */
+ unsigned int expected_http_status;
+};
+
+
+struct MerchantPollOrderStartState
+{
+ /**
+ * The merchant base URL.
+ */
+ const char *merchant_url;
+
+ /**
+ * The handle to the current GET /private/orders/$ORDER_ID request.
+ */
+ struct TALER_MERCHANT_OrderMerchantGetHandle *ogh;
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Reference to a command that created an order.
+ */
+ const char *order_id;
+
+ /**
+ * How long to wait for server to return a response.
+ */
+ struct GNUNET_TIME_Relative timeout;
+
+ /**
+ * Conclude state waiting for completion (if any).
+ */
+ struct MerchantPollOrderConcludeState *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 /poll-payment
+ * command expired or we got a response. Checks if the
+ * result is what we expected.
+ *
+ * @param cls a `struct PollPaymentConcludeState`
+ */
+static void
+conclude_task (void *cls)
+{
+ struct MerchantPollOrderConcludeState *ppc = cls;
+ const struct TALER_TESTING_Command *poll_cmd;
+ struct MerchantPollOrderStartState *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 /private/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);
+ }
+ 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);
+}
+
+
+/**
+ * Callback to process a GET /orders/$ID request
+ *
+ * @param cls closure
+ * @param hr HTTP response details
+ * @param osr order status response details (on success)
+ */
+static void
+merchant_poll_order_cb (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const struct TALER_MERCHANT_OrderStatusResponse *osr)
+{
+ /* FIXME, deeper checks should be implemented here. */
+ struct MerchantPollOrderStartState *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 gts->tip_reference here to
+ // 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 order" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command being run now.
+ * @param is interpreter state.
+ */
+static void
+merchant_poll_order_start_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct MerchantPollOrderStartState *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_merchant_order_get (is->ctx,
+ pos->merchant_url,
+ pos->order_id,
+ NULL,
+ false,
+ pos->timeout,
+ &merchant_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
+merchant_poll_order_start_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct MerchantPollOrderStartState *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_merchant_order_get_cancel (pos->ogh);
+ }
+ GNUNET_free (pos);
+}
+
+
+/**
+ * Start a long poll for GET /private/orders/$ORDER_ID.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_poll_order_start (const char *label,
+ const char *merchant_url,
+ const char *order_id,
+ struct GNUNET_TIME_Relative timeout)
+{
+ struct MerchantPollOrderStartState *pos;
+
+ pos = GNUNET_new (struct MerchantPollOrderStartState);
+ pos->order_id = order_id;
+ pos->merchant_url = merchant_url;
+ pos->timeout = timeout;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = pos,
+ .label = label,
+ .run = &merchant_poll_order_start_run,
+ .cleanup = &merchant_poll_order_start_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
+/**
+ * Run the "GET order" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command being run now.
+ * @param is interpreter state.
+ */
+static void
+merchant_poll_order_conclude_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct MerchantPollOrderConcludeState *poc = cls;
+ const struct TALER_TESTING_Command *poll_cmd;
+ struct MerchantPollOrderStartState *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_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
+merchant_poll_order_conclude_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct MerchantPollOrderConcludeState *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/$ORDER_ID.
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_poll_order_conclude (const char *label,
+ unsigned int http_status,
+ const char *poll_start_reference)
+{
+ struct MerchantPollOrderConcludeState *cps;
+
+ cps = GNUNET_new (struct MerchantPollOrderConcludeState);
+ cps->start_reference = poll_start_reference;
+ cps->expected_http_status = http_status;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = cps,
+ .label = label,
+ .run = &merchant_poll_order_conclude_run,
+ .cleanup = &merchant_poll_order_conclude_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
/* end of testing_api_cmd_merchant_get_order.c */