diff options
author | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-06-30 20:03:45 -0400 |
---|---|---|
committer | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2020-06-30 20:03:45 -0400 |
commit | 2da3c81f9dacb34ddb6a6f087ec85f6225f5e0d2 (patch) | |
tree | 9ebdab00ffe0c136cefd348b43f03d1c80dd9482 /src/backenddb | |
parent | bd6a7e949fa07c7b4c87a694c0037e2df3903665 (diff) | |
download | merchant-2da3c81f9dacb34ddb6a6f087ec85f6225f5e0d2.tar.gz merchant-2da3c81f9dacb34ddb6a6f087ec85f6225f5e0d2.tar.bz2 merchant-2da3c81f9dacb34ddb6a6f087ec85f6225f5e0d2.zip |
improved db tests for transfers
Diffstat (limited to 'src/backenddb')
-rw-r--r-- | src/backenddb/plugin_merchantdb_postgres.c | 15 | ||||
-rw-r--r-- | src/backenddb/test_merchantdb.c | 899 |
2 files changed, 691 insertions, 223 deletions
diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index ae566021..88944c9f 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -1012,6 +1012,7 @@ postgres_update_product (void *cls, TALER_PQ_query_param_json (pd->taxes), TALER_PQ_query_param_amount (&pd->price), GNUNET_PQ_query_param_uint64 (&pd->total_stock), + GNUNET_PQ_query_param_uint64 (&pd->total_sold), GNUNET_PQ_query_param_uint64 (&pd->total_lost), /* $11 */ TALER_PQ_query_param_json (pd->address), GNUNET_PQ_query_param_absolute_time (&pd->next_restock), @@ -6091,18 +6092,20 @@ libtaler_plugin_merchantdb_postgres_init (void *cls) ",price_val=$8" ",price_frac=$9" ",total_stock=$10" - ",total_lost=$11" - ",address=$12" - ",next_restock=$13" + ",total_sold=$11" + ",total_lost=$12" + ",address=$13" + ",next_restock=$14" " WHERE merchant_serial=" " (SELECT merchant_serial" " FROM merchant_instances" " WHERE merchant_id=$1)" " AND product_id=$2" " AND total_stock <= $10" - " AND $10 - total_sold >= $11" - " AND total_lost <= $11", - 13), + " AND total_sold <= $11" + " AND $10 - $11 >= $12" + " AND total_lost <= $12", + 14), /* for postgres_lock_product() */ GNUNET_PQ_make_prepare ("lock_product", diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c index cc63b89c..6ee6a417 100644 --- a/src/backenddb/test_merchantdb.c +++ b/src/backenddb/test_merchantdb.c @@ -1109,14 +1109,42 @@ run_test_products (struct TestProducts_Closure *cls) GNUNET_assert (0 == json_array_append_new (cls->products[0].product.taxes, json_string ("2% sales tax"))); - // cls->products[0].product.total_stock = 40; - // cls->products[0].product.total_sold = 5; - // cls->products[0].product.total_lost = 1; - // TEST that these counters cannot be decreased. - + cls->products[0].product.total_stock = 100; + cls->products[0].product.total_sold = 10; + cls->products[0].product.total_lost = 7; + GNUNET_assert (0 == + json_array_append_new (cls->products[0].product.image, + json_string ( + "http://some-website.com/image.png"))); + GNUNET_assert (0 == + json_array_append_new (cls->products[0].product.address, + json_string ("444 Some Street"))); + cls->products[0].product.next_restock = GNUNET_TIME_absolute_get (); TEST_RET_ON_FAIL (test_update_product (&cls->instance, &cls->products[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + + { + struct ProductData stock_dec = cls->products[0]; + stock_dec.product.total_stock = 40; + TEST_RET_ON_FAIL (test_update_product (&cls->instance, + &stock_dec, + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + } + { + struct ProductData sold_dec = cls->products[0]; + sold_dec.product.total_sold = 5; + TEST_RET_ON_FAIL (test_update_product (&cls->instance, + &sold_dec, + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + } + { + struct ProductData lost_dec = cls->products[0]; + lost_dec.product.total_lost = 1; + TEST_RET_ON_FAIL (test_update_product (&cls->instance, + &lost_dec, + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + } TEST_RET_ON_FAIL (test_lookup_product (&cls->instance, &cls->products[0])); TEST_RET_ON_FAIL (test_update_product (&cls->instance, @@ -1131,6 +1159,17 @@ run_test_products (struct TestProducts_Closure *cls) cls->products)); /* Test locking */ uuid.value[0] = 0x1287346a; + if (0 != plugin->lock_product (plugin->cls, + cls->instance.instance.id, + cls->products[0].id, + &uuid, + 256, + refund_deadline)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lock product failed\n"); + return 1; + } if (1 != plugin->lock_product (plugin->cls, cls->instance.instance.id, cls->products[0].id, @@ -1161,6 +1200,13 @@ run_test_products (struct TestProducts_Closure *cls) "Unlock inventory failed\n"); return 1; } + if (0 != plugin->unlock_inventory (plugin->cls, + &uuid)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unlock inventory failed\n"); + return 1; + } TEST_RET_ON_FAIL (test_delete_product (&cls->instance, &cls->products[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); @@ -1235,15 +1281,18 @@ make_order (const char *order_id, GNUNET_TIME_UNIT_WEEKS); GNUNET_TIME_round_abs (&pay_deadline); GNUNET_TIME_round_abs (&refund_deadline); - json_object_set (order->contract, - "fulfillment_url", - json_string ("a")); - json_object_set (order->contract, - "pay_deadline", - GNUNET_JSON_from_time_abs (pay_deadline)); - json_object_set (order->contract, - "refund_deadline", - GNUNET_JSON_from_time_abs (refund_deadline)); + json_object_set_new (order->contract, + "fulfillment_url", + json_string ("a")); + json_object_set_new (order->contract, + "order_id", + json_string (order_id)); + json_object_set_new (order->contract, + "pay_deadline", + GNUNET_JSON_from_time_abs (pay_deadline)); + json_object_set_new (order->contract, + "refund_deadline", + GNUNET_JSON_from_time_abs (refund_deadline)); } @@ -1895,6 +1944,8 @@ run_test_orders (struct TestOrders_Closure *cls) TEST_RET_ON_FAIL (test_insert_order (&cls->instance, &cls->orders[1], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + serial = get_order_serial (&cls->instance, + &cls->orders[0]); TEST_RET_ON_FAIL (test_lookup_orders (&cls->instance, &filter, 2, @@ -1945,11 +1996,37 @@ run_test_orders (struct TestOrders_Closure *cls) TEST_RET_ON_FAIL (test_lookup_order_status (&cls->instance, &cls->orders[0], false)); + { + struct GNUNET_HashCode h_contract_terms; + bool order_paid = false; + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->lookup_order_status (plugin->cls, + cls->instance.instance.id, + cls->orders[1].id, + &h_contract_terms, + &order_paid)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup order status failed\n"); + return 1; + } + } /* Test lookup payment status */ - TEST_RET_ON_FAIL (test_lookup_payment_status (1, + TEST_RET_ON_FAIL (test_lookup_payment_status (serial, NULL, false, false)); + { + bool paid; + bool wired; + TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == + plugin->lookup_payment_status (plugin->cls, + 256, + NULL, + &paid, + &wired), + "Lookup payment status failed\n"); + } /* Test lookup order status fails for nonexistent order */ { struct GNUNET_HashCode h_contract_terms; @@ -1970,8 +2047,6 @@ run_test_orders (struct TestOrders_Closure *cls) TEST_RET_ON_FAIL (test_mark_contract_paid (&cls->instance, &cls->orders[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); - serial = get_order_serial (&cls->instance, - &cls->orders[0]); TEST_RET_ON_FAIL (test_lookup_payment_status (serial, NULL, true, @@ -1995,6 +2070,21 @@ run_test_orders (struct TestOrders_Closure *cls) TEST_RET_ON_FAIL (test_lookup_order_by_fulfillment (&cls->instance, &cls->orders[0], "test_orders_session")); + { + char *order_id; + if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != + plugin->lookup_order_by_fulfillment (plugin->cls, + cls->instance.instance.id, + "fulfillment_url", + "test_orders_session", + &order_id)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Lookup order by fulfillment failed\n"); + GNUNET_free (order_id); + return 1; + } + } /* Test mark as paid fails for nonexistent order */ TEST_RET_ON_FAIL (test_mark_contract_paid (&cls->instance, &cls->orders[1], @@ -2425,7 +2515,7 @@ test_lookup_deposits (const struct InstanceData *instance, memset (results_matching, 0, sizeof (unsigned int) * deposits_length); - TEST_COND_RET_ON_FAIL (deposits_length == + TEST_COND_RET_ON_FAIL (0 <= plugin->lookup_deposits (plugin->cls, instance->instance.id, h_contract_terms, @@ -2435,7 +2525,8 @@ test_lookup_deposits (const struct InstanceData *instance, if (deposits_length != cmp.results_length) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Lookup deposits failed: incorrect number of results returned\n"); + "Lookup deposits failed: incorrect number of results returned (%d)\n", + cmp.results_length); return 1; } for (unsigned int i = 0; deposits_length > i; ++i) @@ -2796,12 +2887,12 @@ struct TestDeposits_Closure /** * The order data */ - struct OrderData order; + struct OrderData orders[2]; /** * The array of deposits */ - struct DepositData deposits[2]; + struct DepositData deposits[3]; }; @@ -2825,22 +2916,29 @@ pre_test_deposits (struct TestDeposits_Closure *cls) /* Order */ make_order ("test_deposits_od_1", - &cls->order); + &cls->orders[0]); + make_order ("test_deposits_od_2", + &cls->orders[1]); /* Deposit */ make_deposit (&cls->instance, &cls->account, - &cls->order, + &cls->orders[0], &cls->signkey, &cls->deposits[0]); make_deposit (&cls->instance, &cls->account, - &cls->order, + &cls->orders[0], &cls->signkey, &cls->deposits[1]); GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:29.00", &cls->deposits[1].amount_with_fee)); + make_deposit (&cls->instance, + &cls->account, + &cls->orders[1], + &cls->signkey, + &cls->deposits[2]); } @@ -2853,7 +2951,8 @@ static void post_test_deposits (struct TestDeposits_Closure *cls) { free_instance_data (&cls->instance); - json_decref (cls->order.contract); + json_decref (cls->orders[0].contract); + json_decref (cls->orders[1].contract); } @@ -2876,13 +2975,15 @@ run_test_deposits (struct TestDeposits_Closure *cls) /* Insert a signing key */ TEST_RET_ON_FAIL (test_insert_exchange_signkey (&cls->signkey, GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_insert_exchange_signkey (&cls->signkey, + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); /* Insert an order */ TEST_RET_ON_FAIL (test_insert_order (&cls->instance, - &cls->order, + &cls->orders[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* Insert contract terms */ TEST_RET_ON_FAIL (test_insert_contract_terms (&cls->instance, - &cls->order, + &cls->orders[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* Test inserting a deposit */ TEST_RET_ON_FAIL (test_insert_deposit (&cls->instance, @@ -2899,6 +3000,10 @@ run_test_deposits (struct TestDeposits_Closure *cls) &cls->deposits[0].h_contract_terms, 1, cls->deposits)); + TEST_RET_ON_FAIL (test_lookup_deposits (&cls->instance, + &cls->deposits[2].h_contract_terms, + 0, + NULL)); /* Test lookup deposits by contract and coins */ TEST_RET_ON_FAIL (test_lookup_deposits_contract_and_coin ( &cls->instance, @@ -2911,17 +3016,36 @@ run_test_deposits (struct TestDeposits_Closure *cls) &cls->signkey, &cls->deposits[1], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_insert_order (&cls->instance, + &cls->orders[1], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_insert_contract_terms (&cls->instance, + &cls->orders[1], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_insert_deposit (&cls->instance, + &cls->signkey, + &cls->deposits[2], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); TEST_RET_ON_FAIL (test_lookup_deposits (&cls->instance, &cls->deposits[0].h_contract_terms, 2, cls->deposits)); + TEST_RET_ON_FAIL (test_lookup_deposits (&cls->instance, + &cls->deposits[2].h_contract_terms, + 1, + &cls->deposits[2])); /* Test lookup deposits by order */ { uint64_t order_serial = get_order_serial (&cls->instance, - &cls->order); + &cls->orders[0]); TEST_RET_ON_FAIL (test_lookup_deposits_by_order (order_serial, 2, cls->deposits)); + order_serial = get_order_serial (&cls->instance, + &cls->orders[1]); + TEST_RET_ON_FAIL (test_lookup_deposits_by_order (order_serial, + 1, + &cls->deposits[2])); } return 0; } @@ -2943,21 +3067,57 @@ test_deposits (void) } -/* Transfers */ +/* *********** Transfers ********** */ +/** + * Container for wire fee data for an exchange. + */ struct WireFeeData { + /** + * The method used. + */ const char *wire_method; + + /** + * Hash of the wire method. + */ struct GNUNET_HashCode h_wire_method; + + /** + * Wire fee charged. + */ struct TALER_Amount wire_fee; + + /** + * Closing fee charged. + */ struct TALER_Amount closing_fee; + + /** + * Start date of the wire fee. + */ struct GNUNET_TIME_Absolute wire_fee_start; + + /** + * End date of the wire fee. + */ struct GNUNET_TIME_Absolute wire_fee_end; + + /** + * Signature on the wire fee. + */ struct TALER_MasterSignatureP fee_sig; }; +/** + * Creates data for an exchange wire fee. + * + * @param signkey the exchange signing key data. + * @param wire_fee where to store the wire fee data. + */ static void make_wire_fee (const struct ExchangeSignkeyData *signkey, struct WireFeeData *wire_fee) @@ -2997,28 +3157,123 @@ make_wire_fee (const struct ExchangeSignkeyData *signkey, } -struct TransferWithDetails +/** + * Container for wire transfer data. + */ +struct TransferData { + /** + * Id of the transfer. + */ struct TALER_WireTransferIdentifierRawP wtid; - struct TALER_EXCHANGE_TransferData details; + + + /** + * The main data for the transfer. + */ + struct TALER_EXCHANGE_TransferData data; + + /** + * URL to the exchange the transfer was made through. + */ + const char *exchange_url; + + /** + * How much the fee for the deposit was. + */ + struct TALER_Amount deposit_fee; + + /** + * Whether the transfer has been confirmed. + */ + bool confirmed; + + /** + * Whether the transfer has been verified. + */ + bool verified; }; +/** + * Creates a transfer for use with testing. + * + * @param deposits_length length of @e deposits. + * @param deposits list of deposits to combine into one transfer. + * @param transfer where to write the transfer data. + */ +static void +make_transfer (const struct ExchangeSignkeyData *signkey, + unsigned int deposits_length, + const struct DepositData deposits[], + struct TransferData *transfer) +{ + GNUNET_CRYPTO_seed_weak_random (585); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + &transfer->wtid, + sizeof (struct TALER_WireTransferIdentifierRawP)); + transfer->exchange_url = deposits[0].exchange_url; + transfer->verified = false; + transfer->confirmed = false; + + struct TALER_TrackTransferDetails *details = NULL; + + transfer->data.details_length = 0; + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (deposits[0].amount_with_fee.currency, + &transfer->data.total_amount)); + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (deposits[0].amount_with_fee.currency, + &transfer->deposit_fee)); + for (unsigned int i = 0; i < deposits_length; ++i) + { + GNUNET_array_grow (details, + transfer->data.details_length, + i + 1); + details[i].h_contract_terms = deposits[i].h_contract_terms; + details[i].coin_pub = deposits[i].coin_pub; + details[i].coin_value = deposits[i].amount_with_fee; + details[i].coin_fee = deposits[i].deposit_fee; + GNUNET_assert (GNUNET_OK == + TALER_amount_add (&transfer->data.total_amount, + &transfer->data.total_amount, + &deposits[i].amount_with_fee)); + GNUNET_assert (GNUNET_OK == + TALER_amount_add (&transfer->deposit_fee, + &transfer->deposit_fee, + &deposits[i].deposit_fee)); + } + transfer->data.exchange_pub = signkey->exchange_pub; + transfer->data.execution_time = GNUNET_TIME_absolute_get (); + transfer->data.details = details; + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:0.50", + &transfer->data.wire_fee)); +} + + +/** + * Tests looking up a transfer from the database. + * + * @param exchange_url url to the exchange of the transfer. + * @param wtid id of the transfer. + * @param total_expected the total amount of the transfer. + * @param fee_expected the fee on the transfer. + * @param time_expected when the transfer was made. + * @param verified_expected whether the transfer was verified. + * @return 1 on success, 0 otherwise. + */ static int -test_lookup_transfer (const char *exchange_url, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct TALER_Amount *total_expected, - const struct TALER_Amount *fee_expected, - const struct GNUNET_TIME_Absolute *time_expected, - bool verified_expected) +test_lookup_transfer (const struct TransferData *transfer) { + struct TALER_Amount total_with_fee; struct TALER_Amount total; struct TALER_Amount fee; struct GNUNET_TIME_Absolute time; bool verified; if (1 != plugin->lookup_transfer (plugin->cls, - exchange_url, - wtid, + transfer->exchange_url, + &transfer->wtid, &total, &fee, &time, @@ -3028,16 +3283,19 @@ test_lookup_transfer (const char *exchange_url, "Lookup transfer failed\n"); return 1; } - if ((GNUNET_OK != TALER_amount_cmp_currency (total_expected, + GNUNET_assert (GNUNET_OK == TALER_amount_add (&total_with_fee, + &transfer->data.total_amount, + &transfer->data.wire_fee)); + if ((GNUNET_OK != TALER_amount_cmp_currency (&total_with_fee, &total)) || - (0 != TALER_amount_cmp (total_expected, + (0 != TALER_amount_cmp (&total_with_fee, &total)) || - (GNUNET_OK != TALER_amount_cmp_currency (fee_expected, + (GNUNET_OK != TALER_amount_cmp_currency (&transfer->data.wire_fee, &fee)) || - (0 != TALER_amount_cmp (fee_expected, + (0 != TALER_amount_cmp (&transfer->data.wire_fee, &fee)) || - (time_expected->abs_value_us != time.abs_value_us) || - (verified_expected != verified)) + (transfer->data.execution_time.abs_value_us != time.abs_value_us) || + (transfer->verified != verified)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lookup transfer failed: mismatched data\n"); @@ -3047,15 +3305,41 @@ test_lookup_transfer (const char *exchange_url, } +/** + * Closure for testing 'lookup_transfer_summary' + */ struct TestLookupTransferSummary_Closure { + /** + * Id of the order the transfer was made for. + */ const char *order_id; + + /** + * The value of the deposit made. + */ const struct TALER_Amount *deposit_value; + + /** + * The fee on the deposit made. + */ const struct TALER_Amount *deposit_fee; + + /** + * 0 if the comparison is true, 1 if false. + */ int result; }; +/** + * Called after 'test_lookup_transfer_summary'. + * + * @param cls pointer to 'TestLookupTransferSummary_Closure'. + * @param order_id id of the order the transfer was made for. + * @param deposit_value the value of the deposit made. + * @param deposit_fee the fee on the deposit made. + */ static void lookup_transfer_summary_cb (void *cls, const char *order_id, @@ -3081,6 +3365,16 @@ lookup_transfer_summary_cb (void *cls, } +/** + * Tests looking up a transfer's summary. + * + * @param exchange_url url to the exchange for the transfer. + * @param wtid identifier of the transfer. + * @param expected_order_id the id of the order associated with the transfer. + * @param expected_deposit_value the amount of the deposit made for the transfer. + * @param expected_deposit_fee the fee on the deposit made for the transfer. + * @return 1 on success, 0 otherwise. + */ static int test_lookup_transfer_summary (const char *exchange_url, const struct @@ -3115,15 +3409,40 @@ test_lookup_transfer_summary (const char *exchange_url, } +/** + * Closure for testing 'lookup_transfer_details'. + */ struct TestLookupTransferDetails_Closure { + /** + * Length of @e details_to_cmp. + */ unsigned int details_to_cmp_length; + + /** + * The details we expect to find. + */ const struct TALER_TrackTransferDetails *details_to_cmp; + + /** + * Number of results matching each detail in @e details_to_cmp. + */ unsigned int *results_matching; + + /** + * Total number of results found. + */ unsigned int results_length; }; +/** + * Called after 'test_lookup_transfer_details'. + * + * @param cls pointer to 'TestLookupTransferDetails_Closure'. + * @param current_offset offset within transfer details. + * @param details the details that were found. + */ static void lookup_transfer_details_cb (void *cls, unsigned int current_offset, @@ -3156,6 +3475,15 @@ lookup_transfer_details_cb (void *cls, } +/** + * Tests looking up details for a wire transfer. + * + * @param exchange_url url to the exchange. + * @param wtid id of the transfer. + * @param details_length the length of @e details. + * @param details the details we expect to be returned. + * @return 1 on success, 0 otherwise. + */ static int test_lookup_transfer_details (const char *exchange_url, const struct @@ -3203,29 +3531,44 @@ test_lookup_transfer_details (const char *exchange_url, } -struct TransferContainer -{ - struct TALER_WireTransferIdentifierRawP wtid; - const char *exchange_url; - struct GNUNET_TIME_Absolute execution_time; - struct TALER_Amount deposit_value; - struct TALER_Amount deposit_fee; - bool confirmed; -}; - - +/** + * Closure for 'lookup_transfer_details_by_order'. + */ struct TestLookupTransferDetailsByOrder_Closure { + /** + * Length of @e transfers_to_cmp. + */ unsigned int transfers_to_cmp_length; - const struct TransferContainer *transfers_to_cmp; + /** + * List of transfers that we expect to find. + */ + const struct TransferData *transfers_to_cmp; + /** + * How many results match the corresponding element of @e transfers_to_cmp. + */ unsigned int *results_matching; + /** + * Total number of results found. + */ unsigned int results_length; }; +/** + * Called after 'test_lookup_transfer_details_by_order'. + * + * @param cls pointer to 'TestLookupTransferDetailsByOrder_Closure'. + * @param wtid identifier of the transfer found. + * @param exchange_url exchange url of the transfer found. + * @param execution_time when the transfer found occured. + * @param deposit_value amount of the deposit for the transfer found. + * @param deposit_fee amount of the fee for the deposit of the transfer. + * @param transfer_confirmed whether the transfer was confirmed. + */ static void lookup_transfer_details_order_cb (void *cls, const struct @@ -3251,9 +3594,9 @@ lookup_transfer_details_order_cb (void *cls, /*(cmp->transfers_to_cmp[i].execution_time.abs_value_us == execution_time.abs_value_us) &&*/ (GNUNET_OK == TALER_amount_cmp_currency ( - &cmp->transfers_to_cmp[i].deposit_value, + &cmp->transfers_to_cmp[i].data.total_amount, deposit_value)) && - (0 == TALER_amount_cmp (&cmp->transfers_to_cmp[i].deposit_value, + (0 == TALER_amount_cmp (&cmp->transfers_to_cmp[i].data.total_amount, deposit_value)) && (GNUNET_OK == TALER_amount_cmp_currency ( &cmp->transfers_to_cmp[i].deposit_fee, @@ -3266,11 +3609,19 @@ lookup_transfer_details_order_cb (void *cls, } +/** + * Tests looking up wire transfers associated with an order. + * + * @param order_serial the order to be queried. + * @param transfers_length length of @e transfers. + * @param transfers the transfers we expect to be found. + * @return 0 on success, 1 otherwise. + */ static int test_lookup_transfer_details_by_order (uint64_t order_serial, unsigned int transfers_length, const struct - TransferContainer *transfers) + TransferData *transfers) { unsigned int results_matching[transfers_length]; struct TestLookupTransferDetailsByOrder_Closure cmp = { @@ -3311,6 +3662,14 @@ test_lookup_transfer_details_by_order (uint64_t order_serial, } +/** + * Tests inserting wire fee data for an exchange. + * + * @param signkey the signing key for the exchange. + * @param wire_fee the wire fee data. + * @param expected_result what the database should return. + * @return 0 on success, 1 otherwise. + */ static int test_insert_wire_fee (const struct ExchangeSignkeyData *signkey, const struct WireFeeData *wire_fee, @@ -3335,6 +3694,13 @@ test_insert_wire_fee (const struct ExchangeSignkeyData *signkey, } +/** + * Tests looking up wire fee data for an exchange. + * + * @param signkey the signing key to use for lookup. + * @param wire_fee_data the wire fee data we expect to find. + * @return 0 on success, 1 otherwise. + */ static int test_lookup_wire_fee (const struct ExchangeSignkeyData *signkey, const struct WireFeeData *wire_fee_data) @@ -3379,18 +3745,49 @@ test_lookup_wire_fee (const struct ExchangeSignkeyData *signkey, } +/** + * Closure for 'lookup_transfers'. + */ struct TestLookupTransfers_Closure { + /** + * Length of @e transfers_to_cmp. + */ unsigned int transfers_to_cmp_length; - const struct TransferWithDetails *transfers_to_cmp; + /** + * The transfers we expect to find. + */ + const struct TransferData *transfers_to_cmp; + /** + * Number of results matching each transfer. + */ unsigned int *results_matching; + /** + * Total number of results found. + */ unsigned int results_length; }; +/** + * Function called after 'test_lookup_transfers'. + * + * @param cls pointer to 'TestLookupTransfers_Closure'. + * @param credit_amount how much was wired to the merchant (minus fees) + * @param wtid wire transfer identifier + * @param payto_uri target account that received the wire transfer + * @param exchange_url base URL of the exchange that made the wire transfer + * @param transfer_serial_id serial number identifying the transfer in the backend + * @param execution_time when did the exchange make the transfer, #GNUNET_TIME_UNIT_FOREVER_ABS + * if it did not yet happen + * @param verified true if we checked the exchange's answer and liked it, + * false there is a problem (verification failed or did not yet happen) + * @param confirmed true if the merchant confirmed this wire transfer + * false if it is so far only claimed to have been made by the exchange + */ static void lookup_transfers_cb (void *cls, const struct TALER_Amount *credit_amount, @@ -3409,11 +3806,11 @@ lookup_transfers_cb (void *cls, { if ((GNUNET_OK == TALER_amount_cmp_currency ( - &cmp->transfers_to_cmp[i].details.total_amount, + &cmp->transfers_to_cmp[i].data.total_amount, credit_amount)) && - (0 == TALER_amount_cmp (&cmp->transfers_to_cmp[i].details.total_amount, + (0 == TALER_amount_cmp (&cmp->transfers_to_cmp[i].data.total_amount, credit_amount)) && - (cmp->transfers_to_cmp[i].details.execution_time.abs_value_us == + (cmp->transfers_to_cmp[i].data.execution_time.abs_value_us == execution_time.abs_value_us)) { cmp->results_matching[i] += 1; @@ -3423,16 +3820,30 @@ lookup_transfers_cb (void *cls, } +/** + * Tests looking up transfers from the database. + * + * @param instance the instance to lookup from. + * @param account the account the transfer was made to. + * @param before do not return transfers before this time. + * @param after do not return transfers after this time. + * @param limit maximum number of transfers to return. + * @param offset row in the database to start with. + * @param filter_verified how to filter verified transfers. + * @param transfers_length length of @e transfers. + * @param transfers the transfers we expect to find. + * @return 0 on success, 1 otherwise. + */ static int -test_lookup_transfers (const char *instance_id, - const char *payto_uri, +test_lookup_transfers (const struct InstanceData *instance, + const struct TALER_MERCHANTDB_AccountDetails *account, struct GNUNET_TIME_Absolute before, struct GNUNET_TIME_Absolute after, int64_t limit, uint64_t offset, enum TALER_EXCHANGE_YesNoAll filter_verified, unsigned int transfers_length, - const struct TransferWithDetails *transfers) + const struct TransferData *transfers) { unsigned int results_matching[transfers_length]; struct TestLookupTransfers_Closure cmp = { @@ -3445,8 +3856,8 @@ test_lookup_transfers (const char *instance_id, 0, sizeof (unsigned int) * transfers_length); if (1 != plugin->lookup_transfers (plugin->cls, - instance_id, - payto_uri, + instance->instance.id, + account->payto_uri, before, after, limit, @@ -3478,37 +3889,146 @@ test_lookup_transfers (const char *instance_id, } +/** + * Tests inserting a transfer into the database. + * + * @param instance the instance to use. + * @param account the account to transfer to. + * @param transfer the transfer to insert. + * @param expected_result the result we expect the db to return. + * @return 0 on success, 1 otherwise. + */ +static int +test_insert_transfer (const struct InstanceData *instance, + const struct TALER_MERCHANTDB_AccountDetails *account, + const struct TransferData *transfer, + enum GNUNET_DB_QueryStatus expected_result) +{ + TEST_COND_RET_ON_FAIL (expected_result == + plugin->insert_transfer (plugin->cls, + instance->instance.id, + transfer->exchange_url, + &transfer->wtid, + &transfer->data.total_amount, + account->payto_uri, + transfer->confirmed), + "Insert transfer failed\n"); + return 0; +} + + +/** + * Tests linking a deposit to a transfer. + * + * @param instance the instance that the deposit and transfer are for. + * @param signkey the signing used on the deposit. + * @param order the order the deposit and transfer were made for. + * @param transfer the transfer. + * @param expected_result the result the database should return. + * @return 0 on success, 1 otherwise. + */ +static int +test_insert_deposit_to_transfer (const struct InstanceData *instance, + const struct ExchangeSignkeyData *signkey, + const struct OrderData *order, + const struct DepositData *deposit, + const struct TransferData *transfer, + enum GNUNET_DB_QueryStatus expected_result) +{ + const struct TALER_EXCHANGE_DepositData deposit_data = { + .exchange_pub = signkey->exchange_pub, + .exchange_sig = deposit->exchange_sig, + .wtid = transfer->wtid, + .execution_time = transfer->data.execution_time, + .coin_contribution = deposit->amount_with_fee + }; + uint64_t deposit_serial = get_deposit_serial (instance, + order, + deposit); + TEST_COND_RET_ON_FAIL (expected_result == + plugin->insert_deposit_to_transfer (plugin->cls, + deposit_serial, + &deposit_data), + "insert deposit to transfer failed\n"); + return 0; +} + + +/** + * Inserts details for a transfer into the database. + * + * @param instance the instance the transfer is in. + * @param account the destination account for the transfer. + * @param transfer the transfer we are adding details to. + * @param expected_result the result expected from the db. + * @return 0 on success, 1 otherwise. + */ +static int +test_insert_transfer_details (const struct InstanceData *instance, + const struct + TALER_MERCHANTDB_AccountDetails *account, + const struct TransferData *transfer, + enum GNUNET_DB_QueryStatus expected_result) +{ + TEST_COND_RET_ON_FAIL (expected_result == + plugin->insert_transfer_details (plugin->cls, + instance->instance.id, + transfer->exchange_url, + account->payto_uri, + &transfer->wtid, + &transfer->data), + "Insert transfer details failed\n"); + return 0; +} + + +/** + * Container for data used when testing transfers. + */ struct TestTransfers_Closure { + /** + * The instance. + */ struct InstanceData instance; /** - * The account + * The account. */ struct TALER_MERCHANTDB_AccountDetails account; /** - * The exchange signing key + * The exchange signing key. */ struct ExchangeSignkeyData signkey; /** - * The order data + * The order data. */ struct OrderData order; /** - * The deposit data + * The deposit data. */ struct DepositData deposit; /** - * Wire fee data + * Wire fee data. + */ + struct WireFeeData wire_fee[2]; + + /** + * The transfers. */ - struct WireFeeData wire_fee; + struct TransferData transfers[1]; }; +/** + * Prepares for testing transfers. + * + * @param cls the test data. + */ static void pre_test_transfers (struct TestTransfers_Closure *cls) { @@ -3535,10 +4055,28 @@ pre_test_transfers (struct TestTransfers_Closure *cls) /* Wire fee */ make_wire_fee (&cls->signkey, - &cls->wire_fee); + &cls->wire_fee[0]); + make_wire_fee (&cls->signkey, + &cls->wire_fee[1]); + cls->wire_fee[1].wire_method = "wire-method-2"; + GNUNET_CRYPTO_hash (cls->wire_fee[1].wire_method, + strlen (cls->wire_fee[1].wire_method) + 1, + &cls->wire_fee[1].h_wire_method); + + /* Transfers */ + make_transfer (&cls->signkey, + 1, + &cls->deposit, + &cls->transfers[0]); + cls->transfers[0].confirmed = true; } +/** + * Cleans up after testing transfers. + * + * @param cls the test data. + */ static void post_test_transfers (struct TestTransfers_Closure *cls) { @@ -3547,34 +4085,22 @@ post_test_transfers (struct TestTransfers_Closure *cls) } +/** + * Runs the tests for transfers. + * + * @param cls the test data. + * @return 0 on success, 1 otherwise. + */ static int run_test_transfers (struct TestTransfers_Closure *cls) { - struct TALER_WireTransferIdentifierRawP wtid = { - .raw = {0} - }; - struct TALER_Amount amount; - struct TALER_Amount total_with_fee; - struct TALER_EXCHANGE_TransferData transfer_data = { - .exchange_pub = cls->signkey.exchange_pub, - .execution_time = GNUNET_TIME_absolute_get (), - }; - struct TALER_TrackTransferDetails transfer_detail = { - .h_contract_terms = cls->deposit.h_contract_terms, - .coin_pub = cls->deposit.coin_pub, - .coin_value = cls->deposit.amount_with_fee, - .coin_fee = cls->deposit.deposit_fee - }; - struct TransferWithDetails full_transfer_data = { - .wtid = wtid - }; uint64_t order_serial; /* Test lookup wire fee fails when it isn't in the db */ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == plugin->lookup_wire_fee (plugin->cls, &cls->signkey.master_pub, - cls->wire_fee.wire_method, + cls->wire_fee[0].wire_method, GNUNET_TIME_absolute_get (), NULL, NULL, @@ -3584,15 +4110,21 @@ run_test_transfers (struct TestTransfers_Closure *cls) "Lookup wire fee failed\n"); /* Test store wire fee by exchange */ TEST_RET_ON_FAIL (test_insert_wire_fee (&cls->signkey, - &cls->wire_fee, + &cls->wire_fee[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* Test double insertion fails */ TEST_RET_ON_FAIL (test_insert_wire_fee (&cls->signkey, - &cls->wire_fee, + &cls->wire_fee[0], GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); /* Test lookup wire fee by exchange */ TEST_RET_ON_FAIL (test_lookup_wire_fee (&cls->signkey, - &cls->wire_fee)); + &cls->wire_fee[0])); + /* Test different wire fees for different methods. */ + TEST_RET_ON_FAIL (test_insert_wire_fee (&cls->signkey, + &cls->wire_fee[1], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_lookup_wire_fee (&cls->signkey, + &cls->wire_fee[1])); /* Insert the instance */ TEST_RET_ON_FAIL (test_insert_instance (&cls->instance, GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); @@ -3618,146 +4150,79 @@ run_test_transfers (struct TestTransfers_Closure *cls) &cls->signkey, &cls->deposit, GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); - transfer_data.details_length = 1; - transfer_data.details = &transfer_detail; /* Insert the transfer */ - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("EUR:50.00", - &amount)); - TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - plugin->insert_transfer (plugin->cls, - cls->instance.instance.id, - cls->deposit.exchange_url, - &wtid, - &amount, - cls->account.payto_uri, - true), - "Insert transfer failed\n"); - /* Test that double insert fails */ - TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == - plugin->insert_transfer (plugin->cls, - cls->instance.instance.id, - cls->deposit.exchange_url, - &wtid, - &amount, - cls->account.payto_uri, - true), - "Insert transfer failed\n"); - /* Test transfer details */ - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("EUR:50.00", - &transfer_data.total_amount)); - GNUNET_assert (GNUNET_OK == - TALER_string_to_amount ("EUR:0.49", - &transfer_data.wire_fee)); - TEST_RET_ON_FAIL (test_lookup_payment_status (order_serial, - NULL, - false, - false)); - /* Test insert deposit to transfer */ - { - const struct TALER_EXCHANGE_DepositData deposit_data = { - .exchange_pub = cls->signkey.exchange_pub, - .exchange_sig = cls->deposit.exchange_sig, - .wtid = wtid, - .execution_time = transfer_data.execution_time, - .coin_contribution = transfer_data.total_amount - }; - uint64_t deposit_serial = get_deposit_serial (&cls->instance, - &cls->order, - &cls->deposit); - TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - plugin->insert_deposit_to_transfer (plugin->cls, - deposit_serial, - &deposit_data), - "Insert deposit to transfer failed\n"); - TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == - plugin->insert_deposit_to_transfer (plugin->cls, - deposit_serial, - &deposit_data), - "Insert deposit to transfer failed\n"); - } - TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == - plugin->insert_transfer_details (plugin->cls, - cls->instance.instance - .id, - cls->deposit. - exchange_url, - cls->account.payto_uri, - &wtid, - &transfer_data), - "Insert transfer details failed\n"); + TEST_RET_ON_FAIL (test_insert_transfer (&cls->instance, + &cls->account, + &cls->transfers[0], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_insert_transfer (&cls->instance, + &cls->account, + &cls->transfers[0], + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + TEST_RET_ON_FAIL (test_insert_deposit_to_transfer (&cls->instance, + &cls->signkey, + &cls->order, + &cls->deposit, + &cls->transfers[0], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + TEST_RET_ON_FAIL (test_insert_deposit_to_transfer (&cls->instance, + &cls->signkey, + &cls->order, + &cls->deposit, + &cls->transfers[0], + GNUNET_DB_STATUS_SUCCESS_NO_RESULTS)); + TEST_RET_ON_FAIL (test_insert_transfer_details (&cls->instance, + &cls->account, + &cls->transfers[0], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); TEST_RET_ON_FAIL (test_lookup_payment_status (order_serial, NULL, false, true)); - /* Test lookup transfer */ - GNUNET_assert (0 <= TALER_amount_add (&total_with_fee, - &transfer_data.total_amount, - &transfer_data.wire_fee)); - TEST_RET_ON_FAIL (test_lookup_transfer (cls->deposit.exchange_url, - &wtid, - &total_with_fee, - &transfer_data.wire_fee, - &transfer_data.execution_time, - false)); - /* Test set status to verified */ + TEST_RET_ON_FAIL (test_lookup_transfer (&cls->transfers[0])); TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == plugin->set_transfer_status_to_verified (plugin->cls, cls->deposit. exchange_url, - &wtid), + &cls-> + transfers[0]. + wtid), "Set transfer status to verified failed\n"); - TEST_RET_ON_FAIL (test_lookup_transfer (cls->deposit.exchange_url, - &wtid, - &total_with_fee, - &transfer_data.wire_fee, - &transfer_data.execution_time, - true)); - /* Test lookup transfer summary */ + cls->transfers[0].verified = true; + TEST_RET_ON_FAIL (test_lookup_transfer (&cls->transfers[0])); TEST_RET_ON_FAIL (test_lookup_transfer_summary (cls->deposit.exchange_url, - &wtid, + &cls->transfers[0].wtid, cls->order.id, &cls->deposit.amount_with_fee, &cls->deposit.deposit_fee)); - /* Test lookup transfer details */ TEST_RET_ON_FAIL (test_lookup_transfer_details (cls->deposit.exchange_url, - &wtid, + &cls->transfers[0].wtid, 1, - &transfer_detail)); - /* Test lookup transfers */ - full_transfer_data.details = transfer_data; - TEST_RET_ON_FAIL (test_lookup_transfers (cls->instance.instance.id, - cls->account.payto_uri, + &cls->transfers[0].data. + details[0])); + TEST_RET_ON_FAIL (test_lookup_transfer_details_by_order (order_serial, + 1, + &cls->transfers[0])); + TEST_RET_ON_FAIL (test_lookup_transfers (&cls->instance, + &cls->account, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_ZERO_ABS, - 1, + 8, 0, TALER_EXCHANGE_YNA_ALL, 1, - &full_transfer_data)); - /* Test lookup transfer details by order */ - { - const struct TransferContainer transfers[] = { - { - .wtid = wtid, - .exchange_url = cls->deposit.exchange_url, - .execution_time = transfer_data.execution_time, - .deposit_value = cls->deposit.amount_with_fee, - .deposit_fee = cls->deposit.deposit_fee, - .confirmed = true - } - }; - TEST_RET_ON_FAIL (test_lookup_transfer_details_by_order (order_serial, - 1, - transfers)); - } + &cls->transfers[0])); return 0; } +/** + * Takes care of all work for testing transfers. + * + * @return 0 on success, 1 otherwise. + */ static int -test_transfers (void *cls) +test_transfers (void) { struct TestTransfers_Closure test_cls; pre_test_transfers (&test_cls); @@ -5514,7 +5979,7 @@ run_tests (void *cls) TEST_RET_ON_FAIL (test_products ()); TEST_RET_ON_FAIL (test_orders ()); TEST_RET_ON_FAIL (test_deposits ()); - TEST_RET_ON_FAIL (test_transfers (cls)); + TEST_RET_ON_FAIL (test_transfers ()); TEST_RET_ON_FAIL (test_tips (cls)); TEST_RET_ON_FAIL (test_refunds (cls)); TEST_RET_ON_FAIL (test_lookup_orders_all_filters (cls)); @@ -5558,13 +6023,13 @@ run (void *cls) result = run_tests (cls); /* Test dropping tables */ - /*if (GNUNET_OK != plugin->drop_tables (plugin->cls)) + if (GNUNET_OK != plugin->drop_tables (plugin->cls)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Dropping tables failed\n"); result = 77; return; - }*/ + } /* Unload the plugin */ TALER_MERCHANTDB_plugin_unload (plugin); @@ -5576,8 +6041,8 @@ run (void *cls) return; } - /*GNUNET_break (GNUNET_OK == - plugin->drop_tables (plugin->cls));*/ + GNUNET_break (GNUNET_OK == + plugin->drop_tables (plugin->cls)); TALER_MERCHANTDB_plugin_unload (plugin); plugin = NULL; } |