gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] 176/277: cleaned backenddb test code, completed tests f


From: gnunet
Subject: [taler-merchant] 176/277: cleaned backenddb test code, completed tests for instances & products
Date: Sun, 05 Jul 2020 20:51:29 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

commit 03da63d8e21280de188c2d3baec078cf771fc4d7
Author: Jonathan Buchanan <jonathan.russ.buchanan@gmail.com>
AuthorDate: Wed Jun 3 20:45:54 2020 -0400

    cleaned backenddb test code, completed tests for instances & products
---
 src/backenddb/test_merchantdb.c | 1089 ++++++++++++++++-----------------------
 1 file changed, 438 insertions(+), 651 deletions(-)

diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
index a10bf19..fbf0ff0 100644
--- a/src/backenddb/test_merchantdb.c
+++ b/src/backenddb/test_merchantdb.c
@@ -37,11 +37,87 @@ static int result;
  */
 static struct TALER_MERCHANTDB_Plugin *plugin;
 
-#define TEST_RET_ON_FAIL(test) if (0 != test) \
+#define TEST_WITH_FAIL_CLAUSE(test, on_fail) \
+  if (0 != (test)) \
   { \
+    on_fail \
+  }
+
+#define TEST_COND_RET_ON_FAIL(cond, msg) \
+  if (! (cond)) \
+  { \
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \
+                msg); \
     return 1; \
   }
 
+#define TEST_RET_ON_FAIL(__test) \
+  TEST_WITH_FAIL_CLAUSE (__test, \
+                         return 1; \
+                         )
+
+struct InstanceData
+{
+  struct TALER_MERCHANTDB_InstanceSettings instance;
+  struct TALER_MerchantPublicKeyP merchant_pub;
+  struct TALER_MerchantPrivateKeyP merchant_priv;
+};
+
+
+/* Convenience functions */
+static void
+make_instance (char *instance_id,
+               struct InstanceData *instance)
+{
+  GNUNET_CRYPTO_eddsa_key_create (&instance->merchant_priv.eddsa_priv);
+  GNUNET_CRYPTO_eddsa_key_get_public (&instance->merchant_priv.eddsa_priv,
+                                      &instance->merchant_pub.eddsa_pub);
+  instance->instance.id = instance_id;
+  instance->instance.name = "Test";
+  instance->instance.address = json_array ();
+  GNUNET_assert (NULL != instance->instance.address);
+  GNUNET_assert (0 == json_array_append (instance->instance.address,
+                                         json_string ("123 Example St")));
+  instance->instance.jurisdiction = json_array ();
+  GNUNET_assert (NULL != instance->instance.jurisdiction);
+  GNUNET_assert (0 == json_array_append (instance->instance.jurisdiction,
+                                         json_string ("Ohio")));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:1200.40",
+                                         &instance->instance.
+                                         default_max_deposit_fee));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:1200.40",
+                                         &instance->instance.
+                                         default_max_wire_fee));
+  instance->instance.default_wire_fee_amortization = 1;
+  instance->instance.default_wire_transfer_delay =
+    GNUNET_TIME_relative_get_minute_ ();
+  instance->instance.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+}
+
+
+static void
+free_instance_data (struct InstanceData *instance)
+{
+  json_decref (instance->instance.address);
+  json_decref (instance->instance.jurisdiction);
+}
+
+
+static void
+make_account (struct TALER_MERCHANTDB_AccountDetails *account)
+{
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
+                                    &account->h_wire);
+  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
+                                    &account->salt);
+  account->payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
+  account->active = true;
+}
+
+
+/* Instance tests */
 
 /**
  * Instance settings along with corresponding accounts
@@ -183,38 +259,27 @@ lookup_instances_cb (void *cls,
 
 
 static int
-test_insert_instance (const struct TALER_MerchantPublicKeyP *merchant_pub,
-                      const struct TALER_MerchantPrivateKeyP *merchant_priv,
-                      const struct TALER_MERCHANTDB_InstanceSettings *is)
+test_insert_instance (const struct InstanceData *instance,
+                      enum GNUNET_DB_QueryStatus expected_result)
 {
-  if (1 != plugin->insert_instance (plugin->cls,
-                                    merchant_pub,
-                                    merchant_priv,
-                                    is))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Instance insertion failed\n");
-    return 1;
-  }
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->insert_instance (plugin->cls,
+                                                  &instance->merchant_pub,
+                                                  &instance->merchant_priv,
+                                                  &instance->instance),
+                         "Insert instance failed\n");
   return 0;
 }
 
 
 static int
-test_insert_instance_fails (const struct TALER_MerchantPublicKeyP 
*merchant_pub,
-                            const struct
-                            TALER_MerchantPrivateKeyP *merchant_priv,
-                            const struct TALER_MERCHANTDB_InstanceSettings *is)
+test_update_instance (const struct InstanceData *updated_data,
+                      enum GNUNET_DB_QueryStatus expected_result)
 {
-  if (0 != plugin->insert_instance (plugin->cls,
-                                    merchant_pub,
-                                    merchant_priv,
-                                    is))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Instance insertion succeeded when expected to fail\n");
-    return 1;
-  }
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->update_instance (plugin->cls,
+                                                  &updated_data->instance),
+                         "Update instance failed\n");
   return 0;
 }
 
@@ -261,34 +326,40 @@ test_lookup_instances (bool active_only,
 
 
 static int
-test_insert_account (const char *instance_id,
-                     const struct TALER_MERCHANTDB_AccountDetails *account)
+test_delete_instance_private_key (const struct InstanceData *instance,
+                                  enum GNUNET_DB_QueryStatus expected_result)
 {
-  if (1 != plugin->insert_account (plugin->cls,
-                                   instance_id,
-                                   account))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Insert account failed\n");
-    return 1;
-  }
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->delete_instance_private_key (plugin->cls,
+                                                              
instance->instance
+                                                              .id),
+                         "Delete instance private key failed\n");
   return 0;
 }
 
 
 static int
-test_insert_account_fails (const char *instance_id,
-                           const struct
-                           TALER_MERCHANTDB_AccountDetails *account)
+test_insert_account (const struct InstanceData *instance,
+                     const struct TALER_MERCHANTDB_AccountDetails *account,
+                     enum GNUNET_DB_QueryStatus expected_result)
 {
-  if (0 != plugin->insert_account (plugin->cls,
-                                   instance_id,
-                                   account))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Insert account failed\n");
-    return 1;
-  }
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->insert_account (plugin->cls,
+                                                 instance->instance.id,
+                                                 account),
+                         "Insert account failed\n");
+  return 0;
+}
+
+
+static int
+test_inactivate_account (const struct TALER_MERCHANTDB_AccountDetails *account,
+                         enum GNUNET_DB_QueryStatus expected_result)
+{
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->inactivate_account (plugin->cls,
+                                                     &account->h_wire),
+                         "Inactivate account failed\n");
   return 0;
 }
 
@@ -298,25 +369,10 @@ test_insert_account_fails (const char *instance_id,
  */
 struct TestInstances_Closure
 {
-  /**
-   * The instance settings
-   */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
+  struct InstanceData instances[2];
 
-  /**
-   * The accounts array
-   */
   struct TALER_MERCHANTDB_AccountDetails accounts[2];
+
 };
 
 
@@ -327,43 +383,14 @@ static void
 pre_test_instances (struct TestInstances_Closure *cls)
 {
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_instances_inst0",
+                 &cls->instances[0]);
+  make_instance ("test_instances_inst1",
+                 &cls->instances[1]);
 
   /* Accounts */
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->accounts[0].h_wire);
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->accounts[0].salt);
-  cls->accounts[0].payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
-  cls->accounts[0].active = true;
-
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->accounts[1].h_wire);
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->accounts[1].salt);
-  cls->accounts[1].payto_uri = "payto://other-bank/bank.demo.other.net/4";
-  cls->accounts[1].active = true;
+  make_account (&cls->accounts[0]);
+  make_account (&cls->accounts[1]);
 }
 
 
@@ -373,8 +400,8 @@ pre_test_instances (struct TestInstances_Closure *cls)
 static void
 post_test_instances (struct TestInstances_Closure *cls)
 {
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
+  free_instance_data (&cls->instances[0]);
+  free_instance_data (&cls->instances[1]);
 }
 
 
@@ -386,78 +413,67 @@ post_test_instances (struct TestInstances_Closure *cls)
 static int
 run_test_instances (struct TestInstances_Closure *cls)
 {
-  struct InstanceWithAccounts instances[1] = {
+  struct InstanceWithAccounts instances[2] = {
     {
       .accounts_length = 0,
-      .accounts = NULL,
-      .instance = &cls->is
+      .accounts = cls->accounts,
+      .instance = &cls->instances[0].instance
+    },
+    {
+      .accounts_length = 0,
+      .accounts = cls->accounts,
+      .instance = &cls->instances[1].instance
     }
   };
   uint64_t account_serial;
 
   /* Test inserting an instance */
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
-
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instances[0],
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
   /* Test double insertion fails */
-  TEST_RET_ON_FAIL (test_insert_instance_fails (&cls->merchant_pub,
-                                                &cls->merchant_priv,
-                                                &cls->is));
-
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instances[0],
+                                          
GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
   /* Test lookup instances- is our new instance there? */
   TEST_RET_ON_FAIL (test_lookup_instances (false,
                                            1,
                                            instances));
-
   /* Test update instance */
-  cls->is.name = "Test - updated";
-  if (1 != plugin->update_instance (plugin->cls,
-                                    &cls->is))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Update instance failed\n");
-    return 1;
-  }
+  cls->instances[0].instance.name = "Test - updated";
+  TEST_RET_ON_FAIL (test_update_instance (&cls->instances[0],
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
   TEST_RET_ON_FAIL (test_lookup_instances (false,
                                            1,
                                            instances));
-
   /* Test account creation */
-  TEST_RET_ON_FAIL (test_insert_account (cls->is.id,
-                                         &cls->accounts[0]));
-
+  TEST_RET_ON_FAIL (test_insert_account (&cls->instances[0],
+                                         &cls->accounts[0],
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_insert_account (&cls->instances[1],
+                                         &cls->accounts[1],
+                                         GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
   /* Test double account insertion fails */
-  TEST_RET_ON_FAIL (test_insert_account_fails (cls->is.id,
-                                               &cls->accounts[0]));
-
-  /* Test accounts from instance lookup */
+  TEST_RET_ON_FAIL (test_insert_account (&cls->instances[0],
+                                         &cls->accounts[0],
+                                         GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
   instances[0].accounts_length = 1;
-  instances[0].accounts = cls->accounts;
   TEST_RET_ON_FAIL (test_lookup_instances (false,
                                            1,
                                            instances));
-
-  /* Test account inactivation */
-  if (0 > plugin->inactivate_account (plugin->cls,
-                                      &cls->accounts[0].h_wire))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Inactivate account failed\n");
-    return 1;
-  }
+  /* Test inactivate account */
+  TEST_RET_ON_FAIL (test_inactivate_account (&cls->accounts[0],
+                                             
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_inactivate_account (&cls->accounts[1],
+                                             
GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
   cls->accounts[0].active = false;
   TEST_RET_ON_FAIL (test_lookup_instances (false,
                                            1,
                                            instances));
-
-  /* Test multiple accounts */
-
   /* Test lookup account */
-  if (1 != plugin->lookup_account (plugin->cls,
-                                   cls->is.id,
-                                   cls->accounts[0].payto_uri,
-                                   &account_serial))
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+      plugin->lookup_account (plugin->cls,
+                              cls->instances[0].instance.id,
+                              cls->accounts[0].payto_uri,
+                              &account_serial))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Lookup account failed\n");
@@ -469,33 +485,35 @@ run_test_instances (struct TestInstances_Closure *cls)
                 "Lookup account failed: incorrect serial number found\n");
     return 1;
   }
-  if (1 == plugin->lookup_account (plugin->cls,
-                                   cls->is.id,
-                                   "payto://other-uri",
-                                   &account_serial))
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT ==
+      plugin->lookup_account (plugin->cls,
+                              cls->instances[0].instance.id,
+                              "payto://other-uri",
+                              &account_serial))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Lookup account failed: account found where there is none\n");
     return 1;
   }
-
   /* Test instance private key deletion */
-  if (0 > plugin->delete_instance_private_key (plugin->cls,
-                                               cls->is.id))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Delete instance private key failed\n");
-    return 1;
-  }
+  TEST_RET_ON_FAIL (test_delete_instance_private_key (&cls->instances[0],
+                                                      
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_delete_instance_private_key (&cls->instances[1],
+                                                      
GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
   TEST_RET_ON_FAIL (test_lookup_instances (true,
                                            0,
                                            NULL));
   TEST_RET_ON_FAIL (test_lookup_instances (false,
                                            1,
                                            instances));
-
-  /* Test instance deletion */
-
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instances[1],
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_lookup_instances (false,
+                                           2,
+                                           instances));
+  TEST_RET_ON_FAIL (test_lookup_instances (true,
+                                           1,
+                                           &instances[1]));
   return 0;
 }
 
@@ -532,6 +550,48 @@ free_product (struct TALER_MERCHANTDB_ProductDetails *pd)
 }
 
 
+struct ProductData
+{
+  const char *id;
+  struct TALER_MERCHANTDB_ProductDetails product;
+};
+
+
+static void
+make_product (const char *id,
+              struct ProductData *product)
+{
+  product->id = id;
+  product->product.description = "This is a test product";
+  product->product.description_i18n = json_array ();
+  GNUNET_assert (NULL != product->product.description_i18n);
+  product->product.unit = "boxes";
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:120.40",
+                                         &product->product.price));
+  product->product.taxes = json_array ();
+  GNUNET_assert (NULL != product->product.taxes);
+  product->product.total_stock = 55;
+  product->product.total_sold = 0;
+  product->product.total_lost = 0;
+  product->product.image = json_array ();
+  GNUNET_assert (NULL != product->product.image);
+  product->product.address = json_array ();
+  GNUNET_assert (NULL != product->product.address);
+  product->product.next_restock = GNUNET_TIME_absolute_get_zero_ ();
+}
+
+
+static void
+free_product_data (struct ProductData *product)
+{
+  json_decref (product->product.description_i18n);
+  json_decref (product->product.taxes);
+  json_decref (product->product.image);
+  json_decref (product->product.address);
+}
+
+
 /**
  * Closure for testing product lookup
  */
@@ -545,7 +605,7 @@ struct TestLookupProducts_Closure
   /**
    * Pointer to array of product ids
    */
-  const char **product_ids_to_cmp;
+  const struct ProductData *products_to_cmp;
 
   /**
    * Pointer to array of number of matches for each product
@@ -569,7 +629,7 @@ lookup_products_cb (void *cls,
   cmp->results_length += 1;
   for (unsigned int i = 0; cmp->products_to_cmp_length > i; ++i)
   {
-    if (0 == strcmp (cmp->product_ids_to_cmp[i],
+    if (0 == strcmp (cmp->products_to_cmp[i].id,
                      product_id))
       cmp->results_matching[i] += 1;
   }
@@ -606,32 +666,43 @@ check_products_equal (const struct 
TALER_MERCHANTDB_ProductDetails *a,
 
 
 static int
-test_insert_product (const char *is,
-                     const char *pd_id,
-                     const struct TALER_MERCHANTDB_ProductDetails *pd)
+test_insert_product (const struct InstanceData *instance,
+                     const struct ProductData *product,
+                     enum GNUNET_DB_QueryStatus expected_result)
 {
-  if (1 != plugin->insert_product (plugin->cls,
-                                   is,
-                                   pd_id,
-                                   pd))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Insert product failed\n");
-    return 1;
-  }
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->insert_product (plugin->cls,
+                                                 instance->instance.id,
+                                                 product->id,
+                                                 &product->product),
+                         "Insert product failed\n");
+  return 0;
+}
+
+
+static int
+test_update_product (const struct InstanceData *instance,
+                     const struct ProductData *product,
+                     enum GNUNET_DB_QueryStatus expected_result)
+{
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->update_product (plugin->cls,
+                                                 instance->instance.id,
+                                                 product->id,
+                                                 &product->product),
+                         "Update product failed\n");
   return 0;
 }
 
 
 static int
-test_lookup_product (const char *is,
-                     const char *pd_id,
-                     const struct TALER_MERCHANTDB_ProductDetails *to_cmp)
+test_lookup_product (const struct InstanceData *instance,
+                     const struct ProductData *product)
 {
   struct TALER_MERCHANTDB_ProductDetails lookup_result;
   if (0 > plugin->lookup_product (plugin->cls,
-                                  is,
-                                  pd_id,
+                                  instance->instance.id,
+                                  product->id,
                                   &lookup_result))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -639,6 +710,7 @@ test_lookup_product (const char *is,
     free_product (&lookup_result);
     return 1;
   }
+  const struct TALER_MERCHANTDB_ProductDetails *to_cmp = &product->product;
   if (0 != check_products_equal (&lookup_result,
                                  to_cmp))
   {
@@ -653,20 +725,20 @@ test_lookup_product (const char *is,
 
 
 static int
-test_lookup_products (const char *is,
+test_lookup_products (const struct InstanceData *instance,
                       unsigned int products_length,
-                      const char **product_ids)
+                      const struct ProductData *products)
 {
   unsigned int results_matching[products_length];
   struct TestLookupProducts_Closure cls = {
     .products_to_cmp_length = products_length,
-    .product_ids_to_cmp = product_ids,
+    .products_to_cmp = products,
     .results_matching = results_matching,
     .results_length = 0
   };
   memset (results_matching, 0, sizeof (unsigned int) * products_length);
   if (0 > plugin->lookup_products (plugin->cls,
-                                   is,
+                                   instance->instance.id,
                                    &lookup_products_cb,
                                    &cls))
   {
@@ -694,18 +766,15 @@ test_lookup_products (const char *is,
 
 
 static int
-test_delete_product (const char *is,
-                     const char *pd)
+test_delete_product (const struct InstanceData *instance,
+                     const struct ProductData *product,
+                     enum GNUNET_DB_QueryStatus expected_result)
 {
-  if (0 > plugin->delete_product (plugin->cls,
-                                  is,
-                                  pd))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Delete product failed\n");
-    plugin->drop_tables (plugin->cls);
-    return 1;
-  }
+  TEST_COND_RET_ON_FAIL (expected_result ==
+                         plugin->delete_product (plugin->cls,
+                                                 instance->instance.id,
+                                                 product->id),
+                         "Delete product failed\n");
   return 0;
 }
 
@@ -715,30 +784,12 @@ test_delete_product (const char *is,
  */
 struct TestProducts_Closure
 {
-  /**
-   * The instance settings
-   */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
+  struct InstanceData instance;
 
   /**
    * The array of products
    */
-  struct TALER_MERCHANTDB_ProductDetails products[2];
-
-  /**
-   * The array of product ids
-   */
-  const char *product_ids[2];
+  struct ProductData products[2];
 };
 
 
@@ -749,67 +800,21 @@ static void
 pre_test_products (struct TestProducts_Closure *cls)
 {
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst_products";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_inst_products",
+                 &cls->instance);
 
   /* Products */
-  cls->product_ids[0] = "test_products_pd_0";
-  cls->products[0].description = "This is a test product";
-  cls->products[0].description_i18n = json_array ();
-  GNUNET_assert (NULL != cls->products[0].description_i18n);
-  cls->products[0].unit = "boxes";
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:120.40",
-                                         &cls->products[0].price));
-  cls->products[0].taxes = json_array ();
-  GNUNET_assert (NULL != cls->products[0].taxes);
-  cls->products[0].total_stock = 55;
-  cls->products[0].total_sold = 0;
-  cls->products[0].total_lost = 0;
-  cls->products[0].image = json_array ();
-  GNUNET_assert (NULL != cls->products[0].image);
-  cls->products[0].address = json_array ();
-  GNUNET_assert (NULL != cls->products[0].address);
-  cls->products[0].next_restock = GNUNET_TIME_absolute_get_zero_ ();
-
-  cls->product_ids[1] = "test_products_pd_1";
-  cls->products[1].description = "This is a another test product";
-  cls->products[1].description_i18n = json_array ();
-  GNUNET_assert (NULL != cls->products[1].description_i18n);
-  cls->products[1].unit = "cans";
+  make_product ("test_products_pd_0",
+                &cls->products[0]);
+
+  make_product ("test_products_pd_1",
+                &cls->products[1]);
+  cls->products[1].product.description = "This is a another test product";
+  cls->products[1].product.unit = "cans";
   GNUNET_assert (GNUNET_OK ==
                  TALER_string_to_amount ("EUR:4.95",
-                                         &cls->products[1].price));
-  cls->products[1].taxes = json_array ();
-  GNUNET_assert (NULL != cls->products[1].taxes);
-  cls->products[1].total_stock = 5001;
-  cls->products[1].total_sold = 0;
-  cls->products[1].total_lost = 0;
-  cls->products[1].image = json_array ();
-  GNUNET_assert (NULL != cls->products[1].image);
-  cls->products[1].address = json_array ();
-  GNUNET_assert (NULL != cls->products[1].address);
-  cls->products[1].next_restock = GNUNET_TIME_absolute_get_zero_ ();
+                                         &cls->products[1].product.price));
+  cls->products[1].product.total_stock = 5001;
 }
 
 
@@ -819,76 +824,69 @@ pre_test_products (struct TestProducts_Closure *cls)
 static void
 post_test_products (struct TestProducts_Closure *cls)
 {
-  /* Cleanup instance */
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
-
-  /* Cleanup products */
-  json_decref (cls->products[0].description_i18n);
-  json_decref (cls->products[0].taxes);
-  json_decref (cls->products[0].image);
-  json_decref (cls->products[0].address);
-
-  json_decref (cls->products[1].description_i18n);
-  json_decref (cls->products[1].taxes);
-  json_decref (cls->products[1].image);
-  json_decref (cls->products[1].address);
+  free_instance_data (&cls->instance);
+  free_product_data (&cls->products[0]);
+  free_product_data (&cls->products[1]);
 }
 
 
 static int
 run_test_products (struct TestProducts_Closure *cls)
 {
-  /* Insert the instance */
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
+  struct GNUNET_Uuid uuid;
+  struct GNUNET_TIME_Absolute refund_deadline =
+    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
+                              GNUNET_TIME_UNIT_WEEKS);
 
+  /* Test that insert without an instance fails */
+  TEST_RET_ON_FAIL (test_insert_product (&cls->instance,
+                                         &cls->products[0],
+                                         GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
+  /* Insert the instance */
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
   /* Test inserting a product */
-  TEST_RET_ON_FAIL (test_insert_product (cls->is.id,
-                                         cls->product_ids[0],
-                                         &cls->products[0]));
-
+  TEST_RET_ON_FAIL (test_insert_product (&cls->instance,
+                                         &cls->products[0],
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  /* Test that double insert fails */
+  TEST_RET_ON_FAIL (test_insert_product (&cls->instance,
+                                         &cls->products[0],
+                                         GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
   /* Test lookup of individual products */
-  TEST_RET_ON_FAIL (test_lookup_product (cls->is.id,
-                                         cls->product_ids[0],
+  TEST_RET_ON_FAIL (test_lookup_product (&cls->instance,
                                          &cls->products[0]));
-
   /* Make sure it fails correctly for products that don't exist */
-
-  /* Test product update */
-  cls->products[0].description =
-    "This is a test product that has been updated!";
-  if (1 != plugin->update_product (plugin->cls,
-                                   cls->is.id,
-                                   cls->product_ids[0],
-                                   &cls->products[0]))
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
+      plugin->lookup_product (plugin->cls,
+                              cls->instance.instance.id,
+                              "nonexistent_product",
+                              NULL))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Update product failed\n");
+                "Lookup product failed\n");
     return 1;
   }
-  TEST_RET_ON_FAIL (test_lookup_product (cls->is.id,
-                                         cls->product_ids[0],
+  /* Test product update */
+  cls->products[0].product.description =
+    "This is a test product that has been updated!";
+  TEST_RET_ON_FAIL (test_update_product (&cls->instance,
+                                         &cls->products[0],
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_lookup_product (&cls->instance,
                                          &cls->products[0]));
-
   /* Test collective product lookup */
-  TEST_RET_ON_FAIL (test_insert_product (cls->is.id,
-                                         cls->product_ids[1],
-                                         &cls->products[1]));
-  TEST_RET_ON_FAIL (test_lookup_products (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_product (&cls->instance,
+                                         &cls->products[1],
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_lookup_products (&cls->instance,
                                           2,
-                                          cls->product_ids));
-
+                                          cls->products));
   /* Test locking */
-  struct GNUNET_Uuid uuid;
   uuid.value[0] = 0x1287346a;
-  struct GNUNET_TIME_Absolute refund_deadline =
-    GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
-                              GNUNET_TIME_UNIT_WEEKS);
   if (1 != plugin->lock_product (plugin->cls,
-                                 cls->is.id,
-                                 cls->product_ids[0],
+                                 cls->instance.instance.id,
+                                 cls->products[0].id,
                                  &uuid,
                                  1,
                                  refund_deadline))
@@ -897,14 +895,17 @@ run_test_products (struct TestProducts_Closure *cls)
                 "Lock product failed\n");
     return 1;
   }
-
   /* Test product deletion */
-  TEST_RET_ON_FAIL (test_delete_product (cls->is.id,
-                                         cls->product_ids[1]));
-  TEST_RET_ON_FAIL (test_lookup_products (cls->is.id,
+  TEST_RET_ON_FAIL (test_delete_product (&cls->instance,
+                                         &cls->products[1],
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  /* Test double deletion fails */
+  TEST_RET_ON_FAIL (test_delete_product (&cls->instance,
+                                         &cls->products[1],
+                                         GNUNET_DB_STATUS_SUCCESS_NO_RESULTS));
+  TEST_RET_ON_FAIL (test_lookup_products (&cls->instance,
                                           1,
-                                          cls->product_ids));
-
+                                          cls->products));
   /* Test unlocking */
   if (1 != plugin->unlock_inventory (plugin->cls,
                                      &uuid))
@@ -913,12 +914,12 @@ run_test_products (struct TestProducts_Closure *cls)
                 "Unlock inventory failed\n");
     return 1;
   }
-  TEST_RET_ON_FAIL (test_delete_product (cls->is.id,
-                                         cls->product_ids[0]));
-  TEST_RET_ON_FAIL (test_lookup_products (cls->is.id,
+  TEST_RET_ON_FAIL (test_delete_product (&cls->instance,
+                                         &cls->products[0],
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
+  TEST_RET_ON_FAIL (test_lookup_products (&cls->instance,
                                           0,
                                           NULL));
-
   return 0;
 }
 
@@ -1202,30 +1203,8 @@ struct OrderData
  */
 struct TestOrders_Closure
 {
-  /**
-   * The instance settings
-   */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
-
-  /**
-   * The product details
-   */
-  struct TALER_MERCHANTDB_ProductDetails product;
-
-  /**
-   * The product id
-   */
-  const char *product_id;
+  struct InstanceData instance;
+  struct ProductData product;
 
   /**
    * The array of orders
@@ -1246,48 +1225,12 @@ pre_test_orders (struct TestOrders_Closure *cls)
                               GNUNET_TIME_UNIT_WEEKS);
 
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst_orders";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_inst_orders",
+                 &cls->instance);
 
   /* Product */
-  cls->product_id = "test_products_pd_0";
-  cls->product.description = "This is a test product";
-  cls->product.description_i18n = json_array ();
-  GNUNET_assert (NULL != cls->product.description_i18n);
-  cls->product.unit = "boxes";
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:120.40",
-                                         &cls->product.price));
-  cls->product.taxes = json_array ();
-  GNUNET_assert (NULL != cls->product.taxes);
-  cls->product.total_stock = 55;
-  cls->product.total_sold = 0;
-  cls->product.total_lost = 0;
-  cls->product.image = json_array ();
-  GNUNET_assert (NULL != cls->product.image);
-  cls->product.address = json_array ();
-  GNUNET_assert (NULL != cls->product.address);
-  cls->product.next_restock = GNUNET_TIME_absolute_get_zero_ ();
+  make_product ("test_orders_pd_0",
+                &cls->product);
 
   /* Orders */
   cls->orders[0].id = "test_orders_od_0";
@@ -1322,13 +1265,8 @@ pre_test_orders (struct TestOrders_Closure *cls)
 static void
 post_test_orders (struct TestOrders_Closure *cls)
 {
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
-
-  json_decref (cls->product.description_i18n);
-  json_decref (cls->product.taxes);
-  json_decref (cls->product.image);
-  json_decref (cls->product.address);
+  free_instance_data (&cls->instance);
+  free_product_data (&cls->product);
 
   json_decref (cls->orders[0].contract);
   json_decref (cls->orders[1].contract);
@@ -1357,48 +1295,47 @@ run_test_orders (struct TestOrders_Closure *cls)
   struct GNUNET_TIME_Relative expiration = GNUNET_TIME_UNIT_MONTHS;
 
   /* Insert the instance */
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Test inserting an order */
-  TEST_RET_ON_FAIL (test_insert_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_order (cls->instance.instance.id,
                                        cls->orders[0].id,
                                        cls->orders[0].pay_deadline,
                                        cls->orders[0].contract));
 
   /* Test lookup order */
-  TEST_RET_ON_FAIL (test_lookup_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_order (cls->instance.instance.id,
                                        cls->orders[0].id,
                                        cls->orders[0].contract));
 
   /* Make sure it fails correctly for nonexistent orders */
 
   /* Test lookups on multiple orders */
-  TEST_RET_ON_FAIL (test_insert_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_order (cls->instance.instance.id,
                                        cls->orders[1].id,
                                        cls->orders[1].pay_deadline,
                                        cls->orders[1].contract));
 
-  TEST_RET_ON_FAIL (test_lookup_orders (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_orders (cls->instance.instance.id,
                                         &filter,
                                         2,
                                         order_id_list));
 
   /* Test inserting contract terms */
-  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->instance.instance.id,
                                                 cls->orders[0].id,
                                                 cls->orders[0].contract));
 
   /* Test order lock */
-  TEST_RET_ON_FAIL (test_insert_product (cls->is.id,
-                                         cls->product_id,
-                                         &cls->product));
+  TEST_RET_ON_FAIL (test_insert_product (&cls->instance,
+                                         &cls->product,
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
   // TEST_RET_ON_FAIL (test)
   if (1 != plugin->insert_order_lock (plugin->cls,
-                                      cls->is.id,
+                                      cls->instance.instance.id,
                                       cls->orders[0].id,
-                                      cls->product_id,
+                                      cls->product.id,
                                       5))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1407,19 +1344,19 @@ run_test_orders (struct TestOrders_Closure *cls)
   }
 
   /* Test lookup contract terms */
-  TEST_RET_ON_FAIL (test_lookup_contract_terms (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_contract_terms (cls->instance.instance.id,
                                                 cls->orders[0].id,
                                                 cls->orders[0].contract));
 
   /* Test lookup order status */
-  TEST_RET_ON_FAIL (test_lookup_order_status (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_order_status (cls->instance.instance.id,
                                               cls->orders[0].id,
                                               &h_contract_terms,
                                               false));
 
   /* Test marking contracts as paid */
   if (1 != plugin->mark_contract_paid (plugin->cls,
-                                       cls->is.id,
+                                       cls->instance.instance.id,
                                        &h_contract_terms,
                                        "test_orders_session"))
   {
@@ -1427,19 +1364,19 @@ run_test_orders (struct TestOrders_Closure *cls)
                 "Mark contract as paid failed\n");
     return 1;
   }
-  TEST_RET_ON_FAIL (test_lookup_order_status (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_order_status (cls->instance.instance.id,
                                               cls->orders[0].id,
                                               &h_contract_terms,
                                               true));
   filter.paid = TALER_MERCHANTDB_YNA_YES;
-  TEST_RET_ON_FAIL (test_lookup_orders (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_orders (cls->instance.instance.id,
                                         &filter,
                                         1,
                                         order_id_list));
 
   /* Test deleting contract terms */
   if (1 != plugin->delete_contract_terms (plugin->cls,
-                                          cls->is.id,
+                                          cls->instance.instance.id,
                                           cls->orders[0].id,
                                           expiration))
   {
@@ -1449,9 +1386,9 @@ run_test_orders (struct TestOrders_Closure *cls)
   }
 
   /* Test delete order */
-  TEST_RET_ON_FAIL (test_delete_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_delete_order (cls->instance.instance.id,
                                        cls->orders[1].id));
-  TEST_RET_ON_FAIL (test_lookup_orders (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_orders (cls->instance.instance.id,
                                         &filter,
                                         0,
                                         NULL));
@@ -1776,17 +1713,7 @@ struct TestDeposits_Closure
   /**
    * The instance settings
    */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
+  struct InstanceData instance;
 
   /**
    * The merchant account
@@ -1869,36 +1796,11 @@ pre_test_deposits (struct TestDeposits_Closure *cls)
   };
 
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst_deposits";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_inst_deposits",
+                 &cls->instance);
 
   /* Account */
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->account.h_wire);
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->account.salt);
-  cls->account.payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
-  cls->account.active = true;
+  make_account (&cls->account);
 
   /* Signing key */
   GNUNET_CRYPTO_eddsa_key_create (&cls->exchange_priv.eddsa_priv);
@@ -1966,7 +1868,7 @@ pre_test_deposits (struct TestDeposits_Closure *cls)
                      &cls->deposits[0].amount_with_fee);
   TALER_amount_hton (&deposit_sign.deposit_fee,
                      &cls->deposits[0].deposit_fee);
-  deposit_sign.merchant = cls->merchant_pub;
+  deposit_sign.merchant = cls->instance.merchant_pub;
   deposit_sign.coin_pub = cls->deposits[0].coin_pub;
   GNUNET_CRYPTO_eddsa_sign (&cls->exchange_priv.eddsa_priv,
                             &deposit_sign,
@@ -1977,9 +1879,7 @@ pre_test_deposits (struct TestDeposits_Closure *cls)
 static void
 post_test_deposits (struct TestDeposits_Closure *cls)
 {
-  /* Instance */
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
+  free_instance_data (&cls->instance);
 
   /* Order */
   json_decref (cls->order.contract);
@@ -1990,13 +1890,13 @@ static int
 run_test_deposits (struct TestDeposits_Closure *cls)
 {
   /* Insert the instance */
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Insert an account */
-  TEST_RET_ON_FAIL (test_insert_account (cls->is.id,
-                                         &cls->account));
+  TEST_RET_ON_FAIL (test_insert_account (&cls->instance,
+                                         &cls->account,
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Insert a signing key */
   TEST_RET_ON_FAIL (test_insert_exchange_signkey (&cls->master_pub,
@@ -2007,35 +1907,36 @@ run_test_deposits (struct TestDeposits_Closure *cls)
                                                   &cls->master_sig));
 
   /* Insert an order */
-  TEST_RET_ON_FAIL (test_insert_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_order (cls->instance.instance.id,
                                        cls->order.id,
                                        cls->order.pay_deadline,
                                        cls->order.contract));
 
   /* Insert contract terms */
-  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->instance.instance.id,
                                                 cls->order.id,
                                                 cls->order.contract));
 
   /* Test inserting a deposit */
-  TEST_RET_ON_FAIL (test_insert_deposit (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_deposit (cls->instance.instance.id,
                                          &cls->exchange_pub,
                                          &cls->deposits[0]));
 
   /* Test lookup deposits */
-  TEST_RET_ON_FAIL (test_lookup_deposits (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_deposits (cls->instance.instance.id,
                                           &cls->deposits[0].h_contract_terms,
                                           1,
                                           cls->deposits));
 
   /* Test lookup deposits by contract and coins */
-  TEST_RET_ON_FAIL (test_lookup_deposits_contract_and_coin (cls->is.id,
-                                                            &cls->deposits[0].
-                                                            h_contract_terms,
-                                                            &cls->deposits[0].
-                                                            coin_pub,
-                                                            1,
-                                                            cls->deposits));
+  TEST_RET_ON_FAIL (test_lookup_deposits_contract_and_coin (
+                      cls->instance.instance.id,
+                      &cls->deposits[0].
+                      h_contract_terms,
+                      &cls->deposits[0].
+                      coin_pub,
+                      1,
+                      cls->deposits));
 
   return 0;
 }
@@ -2407,20 +2308,7 @@ test_lookup_transfers (const char *instance_id,
 
 struct TestTransfers_Closure
 {
-  /**
-   * The instance settings
-   */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
+  struct InstanceData instance;
 
   /**
    * The account
@@ -2527,36 +2415,11 @@ pre_test_transfers (struct TestTransfers_Closure *cls)
   };
 
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst_transfers";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_inst_transfers",
+                 &cls->instance);
 
   /* Account */
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->account.h_wire);
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->account.salt);
-  cls->account.payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
-  cls->account.active = true;
+  make_account (&cls->account);
 
   /* Order */
   pay_deadline = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
@@ -2610,7 +2473,7 @@ pre_test_transfers (struct TestTransfers_Closure *cls)
                      &cls->deposit.amount_with_fee);
   TALER_amount_hton (&deposit_sign.deposit_fee,
                      &cls->deposit.deposit_fee);
-  deposit_sign.merchant = cls->merchant_pub;
+  deposit_sign.merchant = cls->instance.merchant_pub;
   deposit_sign.coin_pub = cls->deposit.coin_pub;
   GNUNET_CRYPTO_eddsa_sign (&cls->exchange_priv.eddsa_priv,
                             &deposit_sign,
@@ -2660,8 +2523,7 @@ pre_test_transfers (struct TestTransfers_Closure *cls)
 static void
 post_test_transfers (struct TestTransfers_Closure *cls)
 {
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
+  free_instance_data (&cls->instance);
 
   json_decref (cls->order.contract);
 }
@@ -2718,13 +2580,13 @@ run_test_transfers (struct TestTransfers_Closure *cls)
                                           &cls->exch_fee_sig));
 
   /* Insert the instance */
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Insert the account */
-  TEST_RET_ON_FAIL (test_insert_account (cls->is.id,
-                                         &cls->account));
+  TEST_RET_ON_FAIL (test_insert_account (&cls->instance,
+                                         &cls->account,
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Insert a signing key */
   TEST_RET_ON_FAIL (test_insert_exchange_signkey (&cls->master_pub,
@@ -2735,18 +2597,18 @@ run_test_transfers (struct TestTransfers_Closure *cls)
                                                   &cls->master_sig));
 
   /* Insert an order */
-  TEST_RET_ON_FAIL (test_insert_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_order (cls->instance.instance.id,
                                        cls->order.id,
                                        cls->order.pay_deadline,
                                        cls->order.contract));
 
   /* Insert contract terms */
-  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->instance.instance.id,
                                                 cls->order.id,
                                                 cls->order.contract));
 
   /* Insert the deposit */
-  TEST_RET_ON_FAIL (test_insert_deposit (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_deposit (cls->instance.instance.id,
                                          &cls->exchange_pub,
                                          &cls->deposit));
   transfer_data.details_length = 1;
@@ -2757,7 +2619,7 @@ run_test_transfers (struct TestTransfers_Closure *cls)
                  TALER_string_to_amount ("EUR:50.00",
                                          &amount));
   if (1 != plugin->insert_transfer (plugin->cls,
-                                    cls->is.id,
+                                    cls->instance.instance.id,
                                     exchange_url,
                                     &wtid,
                                     &amount,
@@ -2777,7 +2639,7 @@ run_test_transfers (struct TestTransfers_Closure *cls)
                  TALER_string_to_amount ("EUR:0.49",
                                          &transfer_data.wire_fee));
   if (1 != plugin->insert_transfer_details (plugin->cls,
-                                            cls->is.id,
+                                            cls->instance.instance.id,
                                             "exch-url",
                                             cls->account.payto_uri,
                                             &wtid,
@@ -2833,7 +2695,7 @@ run_test_transfers (struct TestTransfers_Closure *cls)
 
   /* Test lookup transfers */
   full_transfer_data.details = transfer_data;
-  TEST_RET_ON_FAIL (test_lookup_transfers (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_transfers (cls->instance.instance.id,
                                            cls->account.payto_uri,
                                            GNUNET_TIME_UNIT_FOREVER_ABS,
                                            GNUNET_TIME_UNIT_ZERO_ABS,
@@ -3323,20 +3185,7 @@ test_lookup_pickup (const char *instance_id,
 
 struct TestTips_Closure
 {
-  /**
-   * The instance settings
-   */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
+  struct InstanceData instance;
 
   /**
    * The tip reserve data
@@ -3357,28 +3206,8 @@ static void
 pre_test_tips (struct TestTips_Closure *cls)
 {
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst_tips";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_inst_tips",
+                 &cls->instance);
 
   /* Reserve */
   GNUNET_CRYPTO_eddsa_key_create (&cls->reserve.reserve_priv.eddsa_priv);
@@ -3409,8 +3238,7 @@ pre_test_tips (struct TestTips_Closure *cls)
 static void
 post_test_tips (struct TestTips_Closure *cls)
 {
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
+  free_instance_data (&cls->instance);
 
   GNUNET_CRYPTO_rsa_private_key_free (cls->pickup_priv);
   GNUNET_CRYPTO_rsa_signature_free (cls->pickup_sig);
@@ -3423,13 +3251,12 @@ run_test_tips (struct TestTips_Closure *cls)
   struct TALER_Amount zero;
   TALER_amount_get_zero ("EUR", &zero);
 
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Test insert reserve */
   if (TALER_EC_NONE != plugin->insert_reserve (plugin->cls,
-                                               cls->is.id,
+                                               cls->instance.instance.id,
                                                &cls->reserve.reserve_priv,
                                                &cls->reserve.reserve_pub,
                                                cls->reserve.exchange_url,
@@ -3442,13 +3269,13 @@ run_test_tips (struct TestTips_Closure *cls)
   }
 
   /* Test lookup reserve */
-  TEST_RET_ON_FAIL (test_lookup_reserve (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_reserve (cls->instance.instance.id,
                                          &cls->reserve.reserve_pub,
                                          &cls->reserve));
 
   /* Test reserve activation */
   if (1 != plugin->activate_reserve (plugin->cls,
-                                     cls->is.id,
+                                     cls->instance.instance.id,
                                      &cls->reserve.reserve_pub,
                                      &cls->reserve.initial_amount))
   {
@@ -3459,7 +3286,7 @@ run_test_tips (struct TestTips_Closure *cls)
 
   /* Test inserting a tip */
   if (TALER_EC_NONE != plugin->authorize_tip (plugin->cls,
-                                              cls->is.id,
+                                              cls->instance.instance.id,
                                               &cls->reserve.reserve_pub,
                                               &cls->tip_amount,
                                               "because",
@@ -3473,7 +3300,7 @@ run_test_tips (struct TestTips_Closure *cls)
   }
 
   /* Test lookup tip */
-  TEST_RET_ON_FAIL (test_lookup_tip (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_tip (cls->instance.instance.id,
                                      &cls->tip_id,
                                      &cls->tip_amount,
                                      &zero,
@@ -3482,7 +3309,7 @@ run_test_tips (struct TestTips_Closure *cls)
                                      &cls->reserve.reserve_priv));
 
   /* Test lookup tip details */
-  TEST_RET_ON_FAIL (test_lookup_tip_details (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_tip_details (cls->instance.instance.id,
                                              cls->tip_id,
                                              &cls->tip_amount,
                                              &zero,
@@ -3494,7 +3321,7 @@ run_test_tips (struct TestTips_Closure *cls)
 
   /* Test insert pickup */
   if (1 != plugin->insert_pickup (plugin->cls,
-                                  cls->is.id,
+                                  cls->instance.instance.id,
                                   &cls->tip_id,
                                   &cls->tip_amount,
                                   &cls->pickup_id,
@@ -3506,7 +3333,7 @@ run_test_tips (struct TestTips_Closure *cls)
   }
 
   /* Test lookup pickup */
-  TEST_RET_ON_FAIL (test_lookup_pickup (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_pickup (cls->instance.instance.id,
                                         &cls->tip_id,
                                         &cls->pickup_id,
                                         cls->reserve.exchange_url,
@@ -3526,13 +3353,13 @@ run_test_tips (struct TestTips_Closure *cls)
   }
 
   /* Test lookup reserves */
-  TEST_RET_ON_FAIL (test_lookup_reserves (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_reserves (cls->instance.instance.id,
                                           1,
                                           &cls->reserve));
 
   /* Test delete reserve private key */
   if (1 != plugin->delete_reserve (plugin->cls,
-                                   cls->is.id,
+                                   cls->instance.instance.id,
                                    &cls->reserve.reserve_pub))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -3542,7 +3369,7 @@ run_test_tips (struct TestTips_Closure *cls)
 
   /* Test purging a reserve */
   if (1 != plugin->purge_reserve (plugin->cls,
-                                  cls->is.id,
+                                  cls->instance.instance.id,
                                   &cls->reserve.reserve_pub))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -3788,20 +3615,7 @@ test_lookup_refund_proof (uint64_t refund_serial,
 
 struct TestRefunds_Closure
 {
-  /**
-   * The instance settings
-   */
-  struct TALER_MERCHANTDB_InstanceSettings is;
-
-  /**
-   * The instance public key
-   */
-  struct TALER_MerchantPublicKeyP merchant_pub;
-
-  /**
-   * The instance private key
-   */
-  struct TALER_MerchantPrivateKeyP merchant_priv;
+  struct InstanceData instance;
 
   /**
    * The merchant account
@@ -3902,36 +3716,11 @@ pre_test_refunds (struct TestRefunds_Closure *cls)
   };
 
   /* Instance */
-  GNUNET_CRYPTO_eddsa_key_create (&cls->merchant_priv.eddsa_priv);
-  GNUNET_CRYPTO_eddsa_key_get_public (&cls->merchant_priv.eddsa_priv,
-                                      &cls->merchant_pub.eddsa_pub);
-  cls->is.id = "test_inst_refunds";
-  cls->is.name = "Test";
-  cls->is.address = json_array ();
-  GNUNET_assert (NULL != cls->is.address);
-  GNUNET_assert (0 == json_array_append (cls->is.address,
-                                         json_string ("123 Example St")));
-  cls->is.jurisdiction = json_array ();
-  GNUNET_assert (NULL != cls->is.jurisdiction);
-  GNUNET_assert (0 == json_array_append (cls->is.jurisdiction,
-                                         json_string ("Ohio")));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_deposit_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_string_to_amount ("EUR:1200.40",
-                                         &cls->is.default_max_wire_fee));
-  cls->is.default_wire_fee_amortization = 1;
-  cls->is.default_wire_transfer_delay = GNUNET_TIME_relative_get_minute_ ();
-  cls->is.default_pay_delay = GNUNET_TIME_relative_get_second_ ();
+  make_instance ("test_inst_refunds",
+                 &cls->instance);
 
   /* Account */
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->account.h_wire);
-  GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_STRONG,
-                                    &cls->account.salt);
-  cls->account.payto_uri = "payto://x-taler-bank/bank.demo.taler.net/4";
-  cls->account.active = true;
+  make_account (&cls->account);
 
   /* Signing key */
   GNUNET_CRYPTO_eddsa_key_create (&cls->exchange_priv.eddsa_priv);
@@ -3999,7 +3788,7 @@ pre_test_refunds (struct TestRefunds_Closure *cls)
                      &cls->deposits[0].amount_with_fee);
   TALER_amount_hton (&deposit_sign.deposit_fee,
                      &cls->deposits[0].deposit_fee);
-  deposit_sign.merchant = cls->merchant_pub;
+  deposit_sign.merchant = cls->instance.merchant_pub;
   deposit_sign.coin_pub = cls->deposits[0].coin_pub;
   GNUNET_CRYPTO_eddsa_sign (&cls->exchange_priv.eddsa_priv,
                             &deposit_sign,
@@ -4036,7 +3825,7 @@ pre_test_refunds (struct TestRefunds_Closure *cls)
                      &cls->deposits[1].amount_with_fee);
   TALER_amount_hton (&deposit_sign.deposit_fee,
                      &cls->deposits[1].deposit_fee);
-  deposit_sign.merchant = cls->merchant_pub;
+  deposit_sign.merchant = cls->instance.merchant_pub;
   deposit_sign.coin_pub = cls->deposits[1].coin_pub;
   GNUNET_CRYPTO_eddsa_sign (&cls->exchange_priv.eddsa_priv,
                             &deposit_sign,
@@ -4062,9 +3851,7 @@ pre_test_refunds (struct TestRefunds_Closure *cls)
 static void
 post_test_refunds (struct TestRefunds_Closure *cls)
 {
-  /* Instance */
-  json_decref (cls->is.address);
-  json_decref (cls->is.jurisdiction);
+  free_instance_data (&cls->instance);
 
   /* Order */
   json_decref (cls->order.contract);
@@ -4075,22 +3862,22 @@ static int
 run_test_refunds (struct TestRefunds_Closure *cls)
 {
   /* Insert an instance */
-  TEST_RET_ON_FAIL (test_insert_instance (&cls->merchant_pub,
-                                          &cls->merchant_priv,
-                                          &cls->is));
+  TEST_RET_ON_FAIL (test_insert_instance (&cls->instance,
+                                          
GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Insert an account */
-  TEST_RET_ON_FAIL (test_insert_account (cls->is.id,
-                                         &cls->account));
+  TEST_RET_ON_FAIL (test_insert_account (&cls->instance,
+                                         &cls->account,
+                                         GNUNET_DB_STATUS_SUCCESS_ONE_RESULT));
 
   /* Insert an order */
-  TEST_RET_ON_FAIL (test_insert_order (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_order (cls->instance.instance.id,
                                        cls->order.id,
                                        cls->order.pay_deadline,
                                        cls->order.contract));
 
   /* Insert contract terms */
-  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_contract_terms (cls->instance.instance.id,
                                                 cls->order.id,
                                                 cls->order.contract));
 
@@ -4103,16 +3890,16 @@ run_test_refunds (struct TestRefunds_Closure *cls)
                                                   &cls->master_sig));
 
   /* Insert a deposit */
-  TEST_RET_ON_FAIL (test_insert_deposit (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_deposit (cls->instance.instance.id,
                                          &cls->exchange_pub,
                                          &cls->deposits[0]));
-  TEST_RET_ON_FAIL (test_insert_deposit (cls->is.id,
+  TEST_RET_ON_FAIL (test_insert_deposit (cls->instance.instance.id,
                                          &cls->exchange_pub,
                                          &cls->deposits[1]));
 
   /* Mark as paid */
   if (1 != plugin->mark_contract_paid (plugin->cls,
-                                       cls->is.id,
+                                       cls->instance.instance.id,
                                        &cls->deposits[0].h_contract_terms,
                                        "test_orders_session"))
   {
@@ -4123,7 +3910,7 @@ run_test_refunds (struct TestRefunds_Closure *cls)
 
   /* Test refund coin */
   if (1 != plugin->refund_coin (plugin->cls,
-                                cls->is.id,
+                                cls->instance.instance.id,
                                 &cls->deposits[0].h_contract_terms,
                                 cls->refund.timestamp,
                                 cls->refund.coin_pub,
@@ -4135,14 +3922,14 @@ run_test_refunds (struct TestRefunds_Closure *cls)
   }
 
   /* Test lookup refunds */
-  TEST_RET_ON_FAIL (test_lookup_refunds (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_refunds (cls->instance.instance.id,
                                          &cls->deposits[0].h_contract_terms,
                                          1,
                                          cls->refund.coin_pub,
                                          &cls->refund.refund_amount));
 
   /* Test lookup refunds detailed */
-  TEST_RET_ON_FAIL (test_lookup_refunds_detailed (cls->is.id,
+  TEST_RET_ON_FAIL (test_lookup_refunds_detailed (cls->instance.instance.id,
                                                   &cls->deposits[0].
                                                   h_contract_terms,
                                                   1,
@@ -4166,7 +3953,7 @@ run_test_refunds (struct TestRefunds_Closure *cls)
                  TALER_string_to_amount ("EUR:1.00",
                                          &inc));
   if (1 != plugin->increase_refund (plugin->cls,
-                                    cls->is.id,
+                                    cls->instance.instance.id,
                                     cls->order.id,
                                     &inc,
                                     "more"))

-- 
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]