diff options
author | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-06-26 23:58:55 -0400 |
---|---|---|
committer | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-06-26 23:58:55 -0400 |
commit | cde317f8e848c61e399c6c3e93264b1736f33e74 (patch) | |
tree | e5efe98d771cf14174ccc31ef5bc6a044ac8e414 /src/testing/testing_api_cmd_merchant_get_order.c | |
parent | ab27991b9a8cf9618891ce74e2d86f8b1a916365 (diff) | |
download | merchant-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.c | 340 |
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 */ |