diff options
author | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-06-29 13:48:40 -0400 |
---|---|---|
committer | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-06-29 13:48:40 -0400 |
commit | b637514b36e6c0f44505fca510f3033b85c932ff (patch) | |
tree | 4e6487c244efd1818221a6afe010465bb0c6906a /src/testing/testing_api_cmd_get_orders.c | |
parent | a118bd2c4951fa7b60737e3cca69e62266a1bcef (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.c | 337 |
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 */ |