gnunet-svn
[Top][All Lists]
Advanced

[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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]