summaryrefslogtreecommitdiff
path: root/src/lib/testing_api_cmd_check_payment.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/testing_api_cmd_check_payment.c')
-rw-r--r--src/lib/testing_api_cmd_check_payment.c306
1 files changed, 291 insertions, 15 deletions
diff --git a/src/lib/testing_api_cmd_check_payment.c b/src/lib/testing_api_cmd_check_payment.c
index 2e988d75..c879b784 100644
--- a/src/lib/testing_api_cmd_check_payment.c
+++ b/src/lib/testing_api_cmd_check_payment.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
+ Copyright (C) 2014-2019 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as
@@ -16,7 +16,6 @@
License along with TALER; see the file COPYING. If not, see
<http://www.gnu.org/licenses/>
*/
-
/**
* @file lib/testing_api_cmd_check_payment.c
* @brief command to test the /check-payment feature.
@@ -31,6 +30,11 @@
/**
+ * State for a /check-payment conclude CMD.
+ */
+struct CheckPaymentConcludeState;
+
+/**
* State for a /check-payment CMD.
*/
struct CheckPaymentState
@@ -47,9 +51,9 @@ struct CheckPaymentState
struct TALER_TESTING_Interpreter *is;
/**
- * Expected HTTP response status code.
+ * The merchant base URL.
*/
- unsigned int http_status;
+ const char *merchant_url;
/**
* Reference to a command that can provide a order id,
@@ -58,14 +62,79 @@ struct CheckPaymentState
const char *proposal_reference;
/**
- * GNUNET_YES if we expect the proposal was paid.
+ * State for a /check-payment conclude CMD.
+ */
+ struct CheckPaymentConcludeState *cs;
+
+ /**
+ * 0 if long-polling is not desired.
*/
- unsigned int expect_paid;
+ struct GNUNET_TIME_Relative timeout;
/**
- * The merchant base URL.
+ * Set to the start time of the @e cpo plus the @e timeout.
*/
- const char *merchant_url;
+ struct GNUNET_TIME_Absolute deadline;
+
+ /**
+ * #GNUNET_YES if we expect the proposal was paid, synchronous variant.
+ */
+ int expect_paid;
+
+ /**
+ * #GNUNET_YES if the proposal was paid.
+ */
+ int paid;
+
+ /**
+ * #GNUNET_YES if the proposal was paid and then refunded
+ */
+ int refunded;
+
+ /**
+ * Observed HTTP response status code.
+ */
+ unsigned int http_status;
+
+ /**
+ * Expected HTTP response status code, synchronous variant.
+ */
+ unsigned int expected_http_status;
+
+};
+
+
+/**
+ * State for a /check-payment conclude CMD.
+ */
+struct CheckPaymentConcludeState
+{
+
+ /**
+ * The interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * Reference to a command that can provide a check payment 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;
+
+ /**
+ * #GNUNET_YES if the proposal was expected to be paid.
+ */
+ int expected_paid;
+
};
@@ -95,6 +164,64 @@ check_payment_cleanup (void *cls,
/**
+ * Task called when either the timeout for the /check-payment
+ * command expired or we got a response. Checks if the
+ * result is what we expected.
+ *
+ * @param cls a `struct CheckPaymentConcludeState`
+ */
+static void
+conclude_task (void *cls)
+{
+ struct CheckPaymentConcludeState *cpc = cls;
+ const struct TALER_TESTING_Command *check_cmd;
+ struct CheckPaymentState *cps;
+ struct GNUNET_TIME_Absolute now;
+
+ cpc->task = NULL;
+ check_cmd =
+ TALER_TESTING_interpreter_lookup_command (cpc->is,
+ cpc->start_reference);
+ cps = check_cmd->cls;
+ if (NULL != cps->cpo)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected /poll/payment to have completed, but it did not!\n");
+ TALER_TESTING_FAIL (cpc->is);
+ }
+ if (cps->http_status != cpc->expected_http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected HTTP status %u, got %u\n",
+ cpc->expected_http_status,
+ cps->http_status);
+ TALER_TESTING_FAIL (cps->is);
+ }
+ now = GNUNET_TIME_absolute_get ();
+ if ( (GNUNET_NO == cps->paid) &&
+ (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 (cps->is);
+ }
+ if (cps->paid != cpc->expected_paid)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Expected paid status %u, got %u\n",
+ cpc->expected_paid,
+ cps->paid);
+ TALER_TESTING_FAIL (cps->is);
+ }
+ TALER_TESTING_interpreter_next (cps->is);
+}
+
+
+/**
* Callback for a /check-payment request.
*
* @param cls closure.
@@ -127,11 +254,28 @@ check_payment_cb (void *cls,
cps->expect_paid,
paid,
taler_pay_uri);
- if (paid != cps->expect_paid)
- TALER_TESTING_FAIL (cps->is);
- if (cps->http_status != http_status)
- TALER_TESTING_FAIL (cps->is);
- TALER_TESTING_interpreter_next (cps->is);
+ cps->paid = paid;
+ cps->http_status = http_status;
+ cps->refunded = refunded;
+ if (0 == cps->timeout.rel_value_us)
+ {
+ /* synchronous variant */
+ if (paid != cps->expect_paid)
+ TALER_TESTING_FAIL (cps->is);
+ if (cps->http_status != http_status)
+ TALER_TESTING_FAIL (cps->is);
+ TALER_TESTING_interpreter_next (cps->is);
+ }
+ else
+ {
+ /* asynchronous variant */
+ if (NULL != cps->cs)
+ {
+ GNUNET_SCHEDULER_cancel (cps->cs->task);
+ cps->cs->task = GNUNET_SCHEDULER_add_now (&conclude_task,
+ cps->cs);
+ }
+ }
}
@@ -166,10 +310,12 @@ check_payment_run (void *cls,
cps->merchant_url,
order_id,
NULL,
- GNUNET_TIME_UNIT_ZERO,
+ cps->timeout,
&check_payment_cb,
cps);
GNUNET_assert (NULL != cps->cpo);
+ if (0 != cps->timeout.rel_value_us)
+ TALER_TESTING_interpreter_next (cps->is);
}
@@ -195,7 +341,7 @@ TALER_TESTING_cmd_check_payment (const char *label,
struct CheckPaymentState *cps;
cps = GNUNET_new (struct CheckPaymentState);
- cps->http_status = http_status;
+ cps->expected_http_status = http_status;
cps->proposal_reference = proposal_reference;
cps->expect_paid = expect_paid;
cps->merchant_url = merchant_url;
@@ -212,4 +358,134 @@ TALER_TESTING_cmd_check_payment (const char *label,
}
+/**
+ * Make a "check payment" test command with long polling support.
+ *
+ * @param label command label.
+ * @param merchant_url merchant base url
+ * @param proposal_reference the proposal whose payment status
+ * is going to be checked.
+ * @param timeout how long to wait during long polling for the reply
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_check_payment_start (const char *label,
+ const char *merchant_url,
+ const char *proposal_reference,
+ struct GNUNET_TIME_Relative timeout)
+{
+ struct CheckPaymentState *cps;
+
+ if (0 == timeout.rel_value_us)
+ timeout.rel_value_us = 1; /* 0 reserved for blocking version */
+ cps = GNUNET_new (struct CheckPaymentState);
+ cps->timeout = timeout;
+ cps->proposal_reference = proposal_reference;
+ cps->merchant_url = merchant_url;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = cps,
+ .label = label,
+ .run = &check_payment_run,
+ .cleanup = &check_payment_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
+/**
+ * Free a /check-payment conclusion CMD, and possibly cancel a pending
+ * operation thereof.
+ *
+ * @param cls closure
+ * @param cmd the command currently getting freed.
+ */
+static void
+check_payment_conclude_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct CheckPaymentConcludeState *cps = cls;
+
+ if (NULL != cps->task)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Command `%s' was not terminated\n",
+ TALER_TESTING_interpreter_get_current_label (
+ cps->is));
+ GNUNET_SCHEDULER_cancel (cps->task);
+ cps->task = NULL;
+ }
+}
+
+
+/**
+ * Run a /check-payment conclusion CMD.
+ *
+ * @param cmd the command currenly being run.
+ * @param cls closure.
+ * @param is interpreter state.
+ */
+static void
+check_payment_conclude_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+ struct CheckPaymentConcludeState *cpc = cls;
+ const struct TALER_TESTING_Command *check_cmd;
+ struct CheckPaymentState *cps;
+
+ cpc->is = is;
+ check_cmd =
+ TALER_TESTING_interpreter_lookup_command (is,
+ cpc->start_reference);
+ GNUNET_assert (check_cmd->run == &check_payment_run);
+ cps = check_cmd->cls;
+ if (NULL == cps->cpo)
+ cpc->task = GNUNET_SCHEDULER_add_now (&conclude_task,
+ cpc);
+ else
+ cpc->task = GNUNET_SCHEDULER_add_at (cps->deadline,
+ &conclude_task,
+ cpc);
+}
+
+
+/**
+ * Expect completion of a long-polled "check payment" test command.
+ *
+ * @param label command label.
+ * @param check_start_reference payment start operation that should have
+ * completed
+ * @param http_status expected HTTP response code.
+ * @param expect_paid #GNUNET_YES if we expect the proposal to be
+ * paid, #GNUNET_NO otherwise.
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_check_payment_conclude (const char *label,
+ unsigned int http_status,
+ const char *poll_start_reference,
+ unsigned int expect_paid)
+{
+ struct CheckPaymentConcludeState *cps;
+
+ cps = GNUNET_new (struct CheckPaymentConcludeState);
+ cps->start_reference = poll_start_reference;
+ cps->expected_paid = expect_paid;
+ cps->expected_http_status = http_status;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = cps,
+ .label = label,
+ .run = &check_payment_conclude_run,
+ .cleanup = &check_payment_conclude_cleanup
+ };
+
+ return cmd;
+ }
+}
+
+
/* end of testing_api_cmd_check_payment.c */