summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2019-11-10 17:21:30 +0100
committerChristian Grothoff <christian@grothoff.org>2019-11-10 17:21:30 +0100
commite9f8d268447dd2f1168a9189ec16e96c0fa3deec (patch)
treea6beef5395c3bd02351e7af73d5f611908205429
parentaa44ae235b484e09dbb49dfdb961a3f576205ca0 (diff)
downloadmerchant-e9f8d268447dd2f1168a9189ec16e96c0fa3deec.tar.gz
merchant-e9f8d268447dd2f1168a9189ec16e96c0fa3deec.tar.bz2
merchant-e9f8d268447dd2f1168a9189ec16e96c0fa3deec.zip
add test for long polling on check-payment
-rw-r--r--src/include/taler_merchant_testing_lib.h36
-rw-r--r--src/lib/test_merchant_api.c14
-rw-r--r--src/lib/testing_api_cmd_check_payment.c306
-rw-r--r--src/lib/testing_api_cmd_poll_payment.c3
4 files changed, 337 insertions, 22 deletions
diff --git a/src/include/taler_merchant_testing_lib.h b/src/include/taler_merchant_testing_lib.h
index ba0c927d..30b1bdf5 100644
--- a/src/include/taler_merchant_testing_lib.h
+++ b/src/include/taler_merchant_testing_lib.h
@@ -120,6 +120,42 @@ TALER_TESTING_cmd_check_payment (const char *label,
const char *proposal_reference,
unsigned int expect_paid);
+
+/**
+ * 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);
+
+
+/**
+ * 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);
+
+
/**
* Start a long-polled "poll-payment" test command.
*
diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c
index 56cbb207..359f20d0 100644
--- a/src/lib/test_merchant_api.c
+++ b/src/lib/test_merchant_api.c
@@ -295,6 +295,10 @@ run (void *cls,
merchant_url,
"create-proposal-1",
GNUNET_TIME_UNIT_MINUTES),
+ TALER_TESTING_cmd_check_payment_start ("check-payment-2",
+ merchant_url,
+ "create-proposal-1",
+ GNUNET_TIME_UNIT_MINUTES),
TALER_TESTING_cmd_pay ("deposit-simple",
merchant_url,
MHD_HTTP_OK,
@@ -307,12 +311,10 @@ run (void *cls,
MHD_HTTP_OK,
"poll-payment-2",
GNUNET_YES),
- TALER_TESTING_cmd_check_payment ("check-payment-2",
- merchant_url,
- MHD_HTTP_OK,
- "create-proposal-1",
- GNUNET_YES),
-
+ TALER_TESTING_cmd_check_payment_conclude ("check-payment-conclude-2",
+ MHD_HTTP_OK,
+ "check-payment-2",
+ GNUNET_YES),
TALER_TESTING_cmd_pay_abort ("pay-abort-2",
merchant_url,
"deposit-simple",
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 */
diff --git a/src/lib/testing_api_cmd_poll_payment.c b/src/lib/testing_api_cmd_poll_payment.c
index c6200fb8..40bc79ec 100644
--- a/src/lib/testing_api_cmd_poll_payment.c
+++ b/src/lib/testing_api_cmd_poll_payment.c
@@ -268,7 +268,7 @@ poll_payment_cb (void *cls,
cps->paid = paid;
cps->http_status = http_status;
cps->refunded = refunded;
- if (refunded)
+ if (GNUNET_YES == refunded)
cps->refund = *refund_amount;
if (NULL != cps->cs)
{
@@ -415,6 +415,7 @@ poll_payment_conclude_run (void *cls,
poll_cmd =
TALER_TESTING_interpreter_lookup_command (is,
ppc->start_reference);
+ GNUNET_assert (poll_cmd->run == &poll_payment_start_run);
cps = poll_cmd->cls;
if (NULL == cps->cpo)
ppc->task = GNUNET_SCHEDULER_add_now (&conclude_task,