[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant] 189/277: created lookup_tips method for backenddb
From: |
gnunet |
Subject: |
[taler-merchant] 189/277: created lookup_tips method for backenddb |
Date: |
Sun, 05 Jul 2020 20:51:42 +0200 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository merchant.
commit 7a9c8b206332c3500ffd733b79aa56b0ea01338a
Author: Jonathan Buchanan <jonathan.russ.buchanan@gmail.com>
AuthorDate: Tue Jun 9 19:49:10 2020 -0400
created lookup_tips method for backenddb
---
src/backenddb/merchant-0001.sql | 2 +-
src/backenddb/plugin_merchantdb_postgres.c | 213 ++++++++++++++++
src/backenddb/test_merchantdb.c | 385 +++++++++++++++++++++++------
src/include/taler_merchantdb_plugin.h | 38 +++
4 files changed, 561 insertions(+), 77 deletions(-)
diff --git a/src/backenddb/merchant-0001.sql b/src/backenddb/merchant-0001.sql
index 34e2cb4..b89f779 100644
--- a/src/backenddb/merchant-0001.sql
+++ b/src/backenddb/merchant-0001.sql
@@ -462,7 +462,7 @@ COMMENT ON TABLE merchant_tip_reserves
CREATE TABLE IF NOT EXISTS merchant_tips
(tip_serial BIGSERIAL PRIMARY KEY
- ,reserve_serial BIGINT NOT NULL UNIQUE
+ ,reserve_serial BIGINT NOT NULL
REFERENCES merchant_tip_reserves (reserve_serial) ON DELETE CASCADE
,tip_id BYTEA NOT NULL UNIQUE CHECK (LENGTH(tip_id)=64)
,justification VARCHAR NOT NULL
diff --git a/src/backenddb/plugin_merchantdb_postgres.c
b/src/backenddb/plugin_merchantdb_postgres.c
index 9d2e507..684e0b3 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -4840,6 +4840,141 @@ postgres_lookup_tip (void *cls,
}
+/**
+ * Context used for postgres_lookup_tips().
+ */
+struct LookupMerchantTipsContext
+{
+ /**
+ * Postgres context.
+ */
+ struct PostgresClosure *pg;
+
+ /**
+ * Function to call with the results.
+ */
+ TALER_MERCHANTDB_TipsCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Internal result.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+};
+
+
+/**
+ * Function to be called with the results of a SELECT statement
+ * that has returned @a num_results results about tips.
+ *
+ * @param[in,out] cls of type `struct LookupTipsContext *`
+ * @param result the postgres result
+ * @param num_result the number of results in @a result
+ */
+static void
+lookup_tips_cb (void *cls,
+ PGresult *result,
+ unsigned int num_results)
+{
+ struct LookupMerchantTipsContext *plc = cls;
+ struct PostgresClosure *pg = plc->pg;
+
+ for (unsigned int i = 0; i < num_results; i++)
+ {
+ uint64_t row_id;
+ struct GNUNET_HashCode tip_id;
+ struct TALER_Amount tip_amount;
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_uint64 ("tip_serial",
+ &row_id),
+ GNUNET_PQ_result_spec_auto_from_type ("tip_id",
+ &tip_id),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+ &tip_amount),
+ GNUNET_PQ_result_spec_end
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_PQ_extract_result (result,
+ rs,
+ i))
+ {
+ GNUNET_break (0);
+ plc->qs = GNUNET_DB_STATUS_HARD_ERROR;
+ return;
+ }
+ plc->cb (plc->cb_cls,
+ row_id,
+ tip_id,
+ tip_amount);
+ GNUNET_PQ_cleanup_result (rs);
+ }
+}
+
+
+/**
+ * Lookup tips
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance should we lookup tips for
+ * @param expired should we include expired tips?
+ * @param limit maximum number of results to return, positive for
+ * ascending row id, negative for descending
+ * @param offset row id to start returning results from
+ * @param cb function to call with tip data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_lookup_tips (void *cls,
+ const char *instance_id,
+ enum TALER_MERCHANTDB_YesNoAll expired,
+ int64_t limit,
+ uint64_t offset,
+ TALER_MERCHANTDB_TipsCallback cb,
+ void *cb_cls)
+{
+ struct PostgresClosure *pg = cls;
+ struct LookupMerchantTipsContext plc = {
+ .pg = pg,
+ .cb = cb,
+ .cb_cls = cb_cls
+ };
+ uint64_t ulimit = (limit > 0) ? limit : -limit;
+ uint8_t bexpired;
+ struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (instance_id),
+ GNUNET_PQ_query_param_uint64 (&ulimit),
+ GNUNET_PQ_query_param_uint64 (&offset),
+ GNUNET_PQ_query_param_absolute_time (&now),
+ GNUNET_PQ_query_param_auto_from_type (&bexpired),
+ GNUNET_PQ_query_param_end
+ };
+ enum GNUNET_DB_QueryStatus qs;
+ char stmt[128];
+
+ bexpired = (TALER_MERCHANTDB_YNA_YES == expired);
+ GNUNET_snprintf (stmt,
+ sizeof (stmt),
+ "lookup_tips_%s%s",
+ (limit > 0) ? "inc" : "dec",
+ (TALER_MERCHANTDB_YNA_ALL == expired) ? "" : "_expired");
+ qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
+ stmt,
+ params,
+ &lookup_tips_cb,
+ &plc);
+ if (0 != plc.qs)
+ return plc.qs;
+ return qs;
+}
+
+
/**
* Closure for #lookup_pickup_details_cb().
*/
@@ -7201,6 +7336,83 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
" FROM merchant_instances"
" WHERE merchant_id=$1)",
2),
+ /* For postgres_lookup_tip() */
+ GNUNET_PQ_make_prepare ("lookup_tips_inc",
+ "SELECT"
+ " tip_serial"
+ ",tip_id"
+ ",amount_val"
+ ",amount_frac"
+ ",CAST($4 as BIGINT)" /* otherwise $4 is unused
and Postgres unhappy */
+ ",CAST($5 as BOOL)" /* otherwise $5 is unused and
Postgres unhappy */
+ " FROM merchant_tips"
+ " JOIN merchant_tip_reserves USING
(reserve_serial)"
+ " WHERE merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " tip_serial > $3"
+ " ORDER BY tip_serial ASC"
+ " LIMIT $2",
+ 5),
+ GNUNET_PQ_make_prepare ("lookup_tips_dec",
+ "SELECT"
+ " tip_serial"
+ ",tip_id"
+ ",amount_val"
+ ",amount_frac"
+ ",CAST($4 as BIGINT)" /* otherwise $4 is unused
and Postgres unhappy */
+ ",CAST($5 as BOOL)" /* otherwise $5 is unused and
Postgres unhappy */
+ " FROM merchant_tips"
+ " JOIN merchant_tip_reserves USING
(reserve_serial)"
+ " WHERE merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " tip_serial < $3"
+ " ORDER BY tip_serial DESC"
+ " LIMIT $2",
+ 5),
+ GNUNET_PQ_make_prepare ("lookup_tips_inc_expired",
+ "SELECT"
+ " tip_serial"
+ ",tip_id"
+ ",amount_val"
+ ",amount_frac"
+ " FROM merchant_tips"
+ " JOIN merchant_tip_reserves USING
(reserve_serial)"
+ " WHERE merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " tip_serial > $3"
+ " AND"
+ " CAST($5 as BOOL) = (merchant_tips.expiration
< $4)"
+ " ORDER BY tip_serial ASC"
+ " LIMIT $2",
+ 5),
+ GNUNET_PQ_make_prepare ("lookup_tips_dec_expired",
+ "SELECT"
+ " tip_serial"
+ ",tip_id"
+ ",amount_val"
+ ",amount_frac"
+ " FROM merchant_tips"
+ " JOIN merchant_tip_reserves USING
(reserve_serial)"
+ " WHERE merchant_serial ="
+ " (SELECT merchant_serial"
+ " FROM merchant_instances"
+ " WHERE merchant_id=$1)"
+ " AND"
+ " tip_serial < $3"
+ " AND"
+ " CAST($5 as BOOL) = (merchant_tips.expiration
< $4)"
+ " ORDER BY tip_serial DESC"
+ " LIMIT $2",
+ 5),
/* for postgres_lookup_tip_details() */
GNUNET_PQ_make_prepare ("lookup_tip_details",
"SELECT"
@@ -7395,6 +7607,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
plugin->authorize_tip = &postgres_authorize_tip;
plugin->lookup_pickup = &postgres_lookup_pickup;
plugin->lookup_tip = &postgres_lookup_tip;
+ plugin->lookup_tips = &postgres_lookup_tips;
plugin->lookup_tip_details = &postgres_lookup_tip_details;
plugin->insert_pickup = &postgres_insert_pickup;
plugin->insert_pickup_blind_signature =
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index 3185675..435182f 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -2905,14 +2905,49 @@ test_lookup_reserves (const char *instance_id,
}
+struct TipData
+{
+ struct TALER_MERCHANTDB_TipDetails details;
+ const char *next_url;
+ struct GNUNET_TIME_Absolute expiration;
+};
+
+
+static void
+make_tip (struct TipData *tip)
+{
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:0.99",
+ &tip->details.total_amount));
+ tip->details.reason = "because";
+ tip->next_url = "https://taler.net";
+}
+
+
static int
-test_lookup_tip (const char *instance_id,
- const struct GNUNET_HashCode *tip_id,
- const struct TALER_Amount *expected_total_authorized,
- const struct TALER_Amount *expected_total_picked_up,
- const struct GNUNET_TIME_Absolute *expected_expiration,
- const char *expected_exchange_url,
- const struct TALER_ReservePrivateKeyP *expected_reserve_priv)
+test_authorize_tip (const struct InstanceData *instance,
+ const struct ReserveData *reserve,
+ struct TipData *tip)
+{
+ TEST_COND_RET_ON_FAIL (TALER_EC_NONE ==
+ plugin->authorize_tip (plugin->cls,
+ instance->instance.id,
+ &reserve->reserve_pub,
+ &tip->details.total_amount,
+ tip->details.reason,
+ tip->next_url,
+ &tip->details.tip_id,
+ &tip->expiration),
+ "Authorize tip failed\n");
+ return 0;
+}
+
+
+static int
+test_lookup_tip (const struct InstanceData *instance,
+ const struct ReserveData *reserve,
+ const struct TipData *tip,
+ const struct TALER_Amount *expected_total_picked_up)
{
struct TALER_Amount total_authorized;
struct TALER_Amount total_picked_up;
@@ -2920,8 +2955,8 @@ test_lookup_tip (const char *instance_id,
char *exchange_url = NULL;
struct TALER_ReservePrivateKeyP reserve_priv;
if (1 != plugin->lookup_tip (plugin->cls,
- instance_id,
- tip_id,
+ instance->instance.id,
+ &tip->details.tip_id,
&total_authorized,
&total_picked_up,
&expiration,
@@ -2934,18 +2969,18 @@ test_lookup_tip (const char *instance_id,
GNUNET_free (exchange_url);
return 1;
}
- if ((GNUNET_OK != TALER_amount_cmp_currency (expected_total_authorized,
+ if ((GNUNET_OK != TALER_amount_cmp_currency (&tip->details.total_amount,
&total_authorized)) ||
- (0 != TALER_amount_cmp (expected_total_authorized,
+ (0 != TALER_amount_cmp (&tip->details.total_amount,
&total_authorized)) ||
(GNUNET_OK != TALER_amount_cmp_currency (expected_total_picked_up,
&total_picked_up)) ||
(0 != TALER_amount_cmp (expected_total_picked_up,
&total_picked_up)) ||
- (expected_expiration->abs_value_us != expiration.abs_value_us) ||
- (0 != strcmp (expected_exchange_url,
+ (tip->expiration.abs_value_us != expiration.abs_value_us) ||
+ (0 != strcmp (reserve->exchange_url,
exchange_url)) ||
- (0 != GNUNET_memcmp (expected_reserve_priv,
+ (0 != GNUNET_memcmp (&reserve->reserve_priv,
&reserve_priv)))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -2961,14 +2996,10 @@ test_lookup_tip (const char *instance_id,
static int
-test_lookup_tip_details (const char *instance_id,
- const struct GNUNET_HashCode tip_id,
- const struct TALER_Amount *expected_total_authorized,
+test_lookup_tip_details (const struct InstanceData *instance,
+ const struct ReserveData *reserve,
+ const struct TipData *tip,
const struct TALER_Amount *expected_total_picked_up,
- const char *expected_justification,
- const struct GNUNET_TIME_Absolute
*expected_expiration,
- const struct
- TALER_ReservePublicKeyP *expected_reserve_pub,
unsigned int expected_pickups_length,
const struct
TALER_MERCHANTDB_PickupDetails *expected_pickups)
@@ -2982,8 +3013,8 @@ test_lookup_tip_details (const char *instance_id,
struct TALER_MERCHANTDB_PickupDetails *pickups = NULL;
unsigned int results_matching[expected_pickups_length];
if (TALER_EC_NONE != plugin->lookup_tip_details (plugin->cls,
- instance_id,
- &tip_id,
+ instance->instance.id,
+ &tip->details.tip_id,
true,
&total_authorized,
&total_picked_up,
@@ -3001,18 +3032,18 @@ test_lookup_tip_details (const char *instance_id,
GNUNET_free (pickups);
return 1;
}
- if ((GNUNET_OK != TALER_amount_cmp_currency (expected_total_authorized,
+ if ((GNUNET_OK != TALER_amount_cmp_currency (&tip->details.total_amount,
&total_authorized)) ||
- (0 != TALER_amount_cmp (expected_total_authorized,
+ (0 != TALER_amount_cmp (&tip->details.total_amount,
&total_authorized)) ||
(GNUNET_OK != TALER_amount_cmp_currency (expected_total_picked_up,
&total_picked_up)) ||
(0 != TALER_amount_cmp (expected_total_picked_up,
&total_picked_up)) ||
- (0 != strcmp (expected_justification,
+ (0 != strcmp (tip->details.reason,
justification)) ||
- (expected_expiration->abs_value_us != expiration.abs_value_us) ||
- (0 != GNUNET_memcmp (expected_reserve_pub,
+ (tip->expiration.abs_value_us != expiration.abs_value_us) ||
+ (0 != GNUNET_memcmp (&reserve->reserve_pub,
&reserve_pub)) ||
(expected_pickups_length != pickups_length))
{
@@ -3152,6 +3183,108 @@ test_lookup_pickup (const char *instance_id,
}
+struct TestLookupTips_Closure
+{
+ unsigned int tips_to_cmp_length;
+ const struct TipData *tips_to_cmp;
+ unsigned int results_length;
+ bool *results_match;
+};
+
+
+static void
+lookup_tips_cb (void *cls,
+ uint64_t row_id,
+ struct GNUNET_HashCode tip_id,
+ struct TALER_Amount amount)
+{
+ struct TestLookupTips_Closure *cmp = cls;
+ if (NULL == cmp)
+ return;
+ unsigned int i = cmp->results_length;
+ cmp->results_length += 1;
+ if (cmp->tips_to_cmp_length > i)
+ {
+ if ((0 == GNUNET_memcmp (&cmp->tips_to_cmp[i].details.tip_id,
+ &tip_id)) &&
+ (GNUNET_OK == TALER_amount_cmp_currency (
+ &cmp->tips_to_cmp[i].details.total_amount,
+ &amount)) &&
+ (0 == TALER_amount_cmp (&cmp->tips_to_cmp[i].details.total_amount,
+ &amount)))
+ cmp->results_match[i] = true;
+ else
+ cmp->results_match[i] = false;
+ }
+}
+
+
+static int
+test_lookup_tips (const struct InstanceData *instance,
+ enum TALER_MERCHANTDB_YesNoAll expired,
+ int64_t limit,
+ uint64_t offset,
+ unsigned int tips_length,
+ const struct TipData *tips)
+{
+ bool results_match[tips_length];
+ struct TestLookupTips_Closure cmp = {
+ .tips_to_cmp_length = tips_length,
+ .tips_to_cmp = tips,
+ .results_length = 0,
+ .results_match = results_match
+ };
+
+ memset (results_match,
+ 0,
+ sizeof (bool) * tips_length);
+ if (0 > plugin->lookup_tips (plugin->cls,
+ instance->instance.id,
+ expired,
+ limit,
+ offset,
+ &lookup_tips_cb,
+ &cmp))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup tips failed\n");
+ return 1;
+ }
+ if (tips_length != cmp.results_length)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup tips failed: incorrect number of results (%d)\n",
+ cmp.results_length);
+ return 1;
+ }
+ for (unsigned int i = 0; i < tips_length; ++i)
+ {
+ if (true != cmp.results_match[i])
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Lookup tips failed: mismatched data\n");
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * Convenience function for testing lookup tips with filters
+ */
+static void
+reverse_tip_data_array (unsigned int tips_length,
+ struct TipData *tips)
+{
+ struct TipData tmp[tips_length];
+ for (unsigned int i = 0; i < tips_length; ++i)
+ tmp[i] = tips[tips_length - 1 - i];
+ for (unsigned int i = 0; i < tips_length; ++i)
+ tips[i] = tmp[i];
+}
+
+
struct TestTips_Closure
{
struct InstanceData instance;
@@ -3160,16 +3293,16 @@ struct TestTips_Closure
* The tip reserve data
*/
struct ReserveData reserve;
+ struct ReserveData expired_reserve;
/* Tip and pickup data */
- struct TALER_Amount tip_amount;
- struct GNUNET_HashCode tip_id;
+ struct TipData tip;
+ struct TipData bigtip;
+ struct TipData tips[5];
+
struct GNUNET_HashCode pickup_id;
struct GNUNET_CRYPTO_RsaPrivateKey *pickup_priv;
struct GNUNET_CRYPTO_RsaSignature *pickup_sig;
-
- struct TALER_Amount tip_2_amount;
- struct GNUNET_HashCode tip_2_id;
};
@@ -3192,23 +3325,40 @@ pre_test_tips (struct TestTips_Closure *cls)
GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_WEEKS);
+ GNUNET_CRYPTO_eddsa_key_create (
+ &cls->expired_reserve.reserve_priv.eddsa_priv);
+ GNUNET_CRYPTO_eddsa_key_get_public (
+ &cls->expired_reserve.reserve_priv.eddsa_priv,
+ &cls->expired_reserve.reserve_pub.
+ eddsa_pub);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount ("EUR:99.99",
+
&cls->expired_reserve.initial_amount));
+ cls->expired_reserve.exchange_url = "exch-url";
+ cls->expired_reserve.expiration = GNUNET_TIME_UNIT_ZERO_ABS;
+
/* Tip/pickup */
+ make_tip (&cls->tip);
+ make_tip (&cls->bigtip);
GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount ("EUR:0.99",
- &cls->tip_amount));
- GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
- &cls->tip_id);
- GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
- &cls->tip_id);
+ TALER_string_to_amount ("EUR:99.90",
+ &cls->bigtip.details.total_amount));
+ for (unsigned int i = 0; i < 5; ++i)
+ {
+ char amount[16];
+ make_tip (&cls->tips[i]);
+ GNUNET_snprintf (amount,
+ 16,
+ "EUR:0.%u0",
+ i + 1);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (amount,
+
&cls->tips[i].details.total_amount));
+ }
+
cls->pickup_priv = GNUNET_CRYPTO_rsa_private_key_create (2048);
cls->pickup_sig = GNUNET_CRYPTO_rsa_sign_fdh (cls->pickup_priv,
&cls->pickup_id);
-
- GNUNET_assert (GNUNET_OK ==
- TALER_string_to_amount ("EUR:99.90",
- &cls->tip_2_amount));
- GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
- &cls->tip_2_id);
}
@@ -3246,46 +3396,33 @@ run_test_tips (struct TestTips_Closure *cls)
&cls->reserve.initial_amount),
"Activate reserve failed\n");
/* Test inserting a tip */
- TEST_COND_RET_ON_FAIL (TALER_EC_NONE ==
- plugin->authorize_tip (plugin->cls,
- cls->instance.instance.id,
- &cls->reserve.reserve_pub,
- &cls->tip_amount,
- "because",
- "https://taler.net",
- &cls->tip_id,
- &cls->reserve.expiration),
- "Authorize tip failed\n");
+ TEST_RET_ON_FAIL (test_authorize_tip (&cls->instance,
+ &cls->reserve,
+ &cls->tip));
/* Test lookup tip */
- TEST_RET_ON_FAIL (test_lookup_tip (cls->instance.instance.id,
- &cls->tip_id,
- &cls->tip_amount,
- &zero,
- &cls->reserve.expiration,
- cls->reserve.exchange_url,
- &cls->reserve.reserve_priv));
+ TEST_RET_ON_FAIL (test_lookup_tip (&cls->instance,
+ &cls->reserve,
+ &cls->tip,
+ &zero));
/* Test lookup tip details */
- TEST_RET_ON_FAIL (test_lookup_tip_details (cls->instance.instance.id,
- cls->tip_id,
- &cls->tip_amount,
+ TEST_RET_ON_FAIL (test_lookup_tip_details (&cls->instance,
+ &cls->reserve,
+ &cls->tip,
&zero,
- "because",
- &cls->reserve.expiration,
- &cls->reserve.reserve_pub,
0,
NULL));
/* Test insert pickup */
TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
plugin->insert_pickup (plugin->cls,
cls->instance.instance.id,
- &cls->tip_id,
- &cls->tip_amount,
+ &cls->tip.details.tip_id,
+ &cls->tip.details.total_amount,
&cls->pickup_id,
- &cls->tip_amount),
+
&cls->tip.details.total_amount),
"Insert pickup failed\n");
/* Test lookup pickup */
TEST_RET_ON_FAIL (test_lookup_pickup (cls->instance.instance.id,
- &cls->tip_id,
+ &cls->tip.details.tip_id,
&cls->pickup_id,
cls->reserve.exchange_url,
&cls->reserve.reserve_priv,
@@ -3303,16 +3440,112 @@ run_test_tips (struct TestTips_Closure *cls)
plugin->authorize_tip (plugin->cls,
cls->instance.instance.id,
&cls->reserve.reserve_pub,
- &cls->tip_2_amount,
- "because",
- "https://taler.net",
- &cls->tip_2_id,
+ &cls->bigtip.details.
+ total_amount,
+ cls->bigtip.details.reason,
+ cls->bigtip.next_url,
+ &cls->bigtip.details.tip_id,
&cls->reserve.expiration),
"Authorize tip failed\n");
+ /* Test lookup tips */
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_ALL,
+ 1,
+ 0,
+ 1,
+ &cls->tip));
/* Test lookup reserves */
TEST_RET_ON_FAIL (test_lookup_reserves (cls->instance.instance.id,
1,
&cls->reserve));
+ {
+ /* Test lookup tips & friends */
+ struct TipData expected_tips[6];
+ expected_tips[0] = cls->tip;
+ TEST_RET_ON_FAIL (test_insert_reserve (&cls->instance,
+ &cls->expired_reserve,
+ TALER_EC_NONE));
+ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
+ plugin->activate_reserve (plugin->cls,
+ cls->instance.instance.id,
+ &cls->expired_reserve.
+ reserve_pub,
+ &cls->expired_reserve.
+ initial_amount),
+ "Activate reserve failed\n");
+ for (unsigned int i = 0; i < 5; ++i)
+ {
+ if (i % 2 == 0)
+ {
+ TEST_RET_ON_FAIL (test_authorize_tip (&cls->instance,
+ &cls->expired_reserve,
+ &cls->tips[i]));
+ }
+ else
+ {
+ TEST_RET_ON_FAIL (test_authorize_tip (&cls->instance,
+ &cls->reserve,
+ &cls->tips[i]));
+ }
+ }
+ GNUNET_memcpy (&expected_tips[1],
+ cls->tips,
+ sizeof (struct TipData) * 5);
+ /* Test lookup tips inc */
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_ALL,
+ 6,
+ 0,
+ 6,
+ expected_tips));
+ reverse_tip_data_array (6,
+ expected_tips);
+ /* Test lookup tips dec */
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_ALL,
+ -6,
+ 10,
+ 6,
+ expected_tips));
+ /* Test lookup tips expired inc */
+ expected_tips[0] = cls->tips[0];
+ expected_tips[1] = cls->tips[2];
+ expected_tips[2] = cls->tips[4];
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_YES,
+ 6,
+ 0,
+ 3,
+ expected_tips));
+ /* Test lookup tips expired dec */
+ reverse_tip_data_array (3,
+ expected_tips);
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_YES,
+ -6,
+ 10,
+ 3,
+ expected_tips));
+ /* Test lookup tips unexpired inc */
+ expected_tips[0] = cls->tip;
+ expected_tips[1] = cls->tips[1];
+ expected_tips[2] = cls->tips[3];
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_NO,
+ 6,
+ 0,
+ 3,
+ expected_tips));
+ /* Test lookup tips unexpired dec */
+ reverse_tip_data_array (3,
+ expected_tips);
+ TEST_RET_ON_FAIL (test_lookup_tips (&cls->instance,
+ TALER_MERCHANTDB_YNA_NO,
+ -6,
+ 10,
+ 3,
+ expected_tips));
+ }
/* Test delete reserve private key */
TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
plugin->delete_reserve (plugin->cls,
diff --git a/src/include/taler_merchantdb_plugin.h
b/src/include/taler_merchantdb_plugin.h
index 6f3db87..29550c4 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -580,6 +580,21 @@ typedef void
const struct TALER_MERCHANTDB_TipDetails *tips);
+/**
+ * Typically called by `lookup_tips`.
+ *
+ * @param cls closure
+ * @param row_id row of the tip in the database
+ * @param tip_id id of the tip
+ * @param amount amount of the tip
+ */
+typedef void
+(*TALER_MERCHANTDB_TipsCallback)(void *cls,
+ uint64_t row_id,
+ struct GNUNET_HashCode tip_id,
+ struct TALER_Amount amount);
+
+
/**
* Function called with information about a coin that was deposited.
*
@@ -1847,6 +1862,29 @@ struct TALER_MERCHANTDB_Plugin
struct TALER_ReservePrivateKeyP *reserve_priv);
+ /**
+ * Lookup tips
+ *
+ * @param cls closure, typically a connection to the db
+ * @param instance_id which instance should we lookup tips for
+ * @param expired should we include expired tips?
+ * @param limit maximum number of results to return, positive for
+ * ascending row id, negative for descending
+ * @param offset row id to start returning results from
+ * @param cb function to call with tip data
+ * @param cb_cls closure for @a cb
+ * @return transaction status
+ */
+ enum GNUNET_DB_QueryStatus
+ (*lookup_tips)(void *cls,
+ const char *instance_id,
+ enum TALER_MERCHANTDB_YesNoAll expired,
+ int64_t limit,
+ uint64_t offset,
+ TALER_MERCHANTDB_TipsCallback cb,
+ void *cb_cls);
+
+
/**
* Lookup tip details for tip @a tip_id.
*
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-merchant] 178/277: work on GET /private/orders/ID", (continued)
- [taler-merchant] 178/277: work on GET /private/orders/ID", gnunet, 2020/07/05
- [taler-merchant] 177/277: wrote method for delete reserve, gnunet, 2020/07/05
- [taler-merchant] 184/277: work on implementing GET /private/orders/ID, gnunet, 2020/07/05
- [taler-merchant] 183/277: work on getting TransactionWireTransfer reply built, gnunet, 2020/07/05
- [taler-merchant] 180/277: more work on private-get-orders-ID, gnunet, 2020/07/05
- [taler-merchant] 186/277: start to build get-orders-ID, gnunet, 2020/07/05
- [taler-merchant] 181/277: more test cleanup and some lookup_orders filter tests, gnunet, 2020/07/05
- [taler-merchant] 192/277: need #include, gnunet, 2020/07/05
- [taler-merchant] 197/277: remove from waiting list when resuming, gnunet, 2020/07/05
- [taler-merchant] 196/277: do not forget to kick MHD, gnunet, 2020/07/05
- [taler-merchant] 189/277: created lookup_tips method for backenddb,
gnunet <=
- [taler-merchant] 194/277: finish FIXMEs in private-get-orders-ID:, gnunet, 2020/07/05
- [taler-merchant] 195/277: remark, gnunet, 2020/07/05
- [taler-merchant] 182/277: More complete tests for deposits, transfers, refund, lookup orders, gnunet, 2020/07/05
- [taler-merchant] 187/277: Merge branch 'protocolV1' of git+ssh://git.taler.net/merchant into protocolV1, gnunet, 2020/07/05
- [taler-merchant] 190/277: implementation of GET /private/tips, gnunet, 2020/07/05
- [taler-merchant] 191/277: test/fix for POST /private/reserves, gnunet, 2020/07/05
- [taler-merchant] 193/277: Merge branch 'protocolV1' of git+ssh://git.taler.net/merchant into protocolV1, gnunet, 2020/07/05
- [taler-merchant] 198/277: enable handler, gnunet, 2020/07/05
- [taler-merchant] 200/277: test with MHD error, gnunet, 2020/07/05
- [taler-merchant] 201/277: fix crash, gnunet, 2020/07/05