From 5f9fb50a602c28227911e87921e9bd911023971a Mon Sep 17 00:00:00 2001 From: Jonathan Buchanan Date: Wed, 12 Aug 2020 02:14:19 -0400 Subject: fix/test multiple refund increases for a single coin --- src/backenddb/plugin_merchantdb_postgres.c | 1 + src/backenddb/test_merchantdb.c | 133 ++++++++++++++++++++++------- 2 files changed, 103 insertions(+), 31 deletions(-) (limited to 'src/backenddb') diff --git a/src/backenddb/plugin_merchantdb_postgres.c b/src/backenddb/plugin_merchantdb_postgres.c index 41e4ff38..83a4cea2 100644 --- a/src/backenddb/plugin_merchantdb_postgres.c +++ b/src/backenddb/plugin_merchantdb_postgres.c @@ -2791,6 +2791,7 @@ process_deposits_for_refund_cb (void *cls, return; } rcd[i].refund_amount = ictx.refunded_amount; + rcd[i].max_rtransaction_id = ictx.max_rtransaction_id; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Existing refund for coin %s is %s\n", TALER_B2S (&rcd[i].coin_pub), diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c index 27d6212a..bc6fa514 100644 --- a/src/backenddb/test_merchantdb.c +++ b/src/backenddb/test_merchantdb.c @@ -5782,6 +5782,13 @@ struct TestLookupRefundsDetailed_Closure */ const struct RefundData *refunds_to_cmp; + /** + * Whether to compare the timestamps or not (if we don't have direct control + * of the timestamps, there will be differences on the order of microseconds + * that can be ignored). + */ + bool cmp_timestamps; + /** * The number of results matching each refund. */ @@ -5823,8 +5830,9 @@ lookup_refunds_detailed_cb (void *cls, cmp->results_length += 1; for (unsigned int i = 0; cmp->refunds_to_cmp_length > i; ++i) { - if ((cmp->refunds_to_cmp[i].timestamp.abs_value_us == - timestamp.abs_value_us) && + if (((cmp->refunds_to_cmp[i].timestamp.abs_value_us == + timestamp.abs_value_us) || + !cmp->cmp_timestamps) && (0 == GNUNET_memcmp (cmp->refunds_to_cmp[i].coin_pub, coin_pub)) && (0 == strcmp (cmp->refunds_to_cmp[i].exchange_url, @@ -5847,6 +5855,7 @@ lookup_refunds_detailed_cb (void *cls, * Tests looking up refunds with details from the database. * @param instance the instance to lookup from. * @param h_contract_terms the contract terms the refunds were made for. + * @param cmp_timestamps whether to compare timestamps or not. * @param refunds_length length of @e refunds. * @param refunds the refunds we expect to be returned. * @@ -5855,6 +5864,7 @@ lookup_refunds_detailed_cb (void *cls, static int test_lookup_refunds_detailed (const struct InstanceData *instance, const struct GNUNET_HashCode *h_contract_terms, + bool cmp_timestamps, unsigned int refunds_length, const struct RefundData *refunds) { @@ -5862,15 +5872,16 @@ test_lookup_refunds_detailed (const struct InstanceData *instance, struct TestLookupRefundsDetailed_Closure cmp = { .refunds_to_cmp_length = refunds_length, .refunds_to_cmp = refunds, + .cmp_timestamps = cmp_timestamps, .results_matching = results_matching, .results_length = 0 }; memset (results_matching, 0, sizeof (unsigned int) * refunds_length); - if (1 != plugin->lookup_refunds_detailed (plugin->cls, - instance->instance.id, - h_contract_terms, - &lookup_refunds_detailed_cb, - &cmp)) + if (0 > plugin->lookup_refunds_detailed (plugin->cls, + instance->instance.id, + h_contract_terms, + &lookup_refunds_detailed_cb, + &cmp)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Lookup refunds detailed failed\n"); @@ -6046,17 +6057,17 @@ struct TestRefunds_Closure /** * The order data. */ - struct OrderData order; + struct OrderData orders[2]; /** * The deposit data. */ - struct DepositData deposits[2]; + struct DepositData deposits[3]; /** * The refund data. */ - struct RefundData refund; + struct RefundData refunds[3]; /** * The refund proof data. @@ -6093,23 +6104,42 @@ pre_test_refunds (struct TestRefunds_Closure *cls) /* Order */ make_order ("test_refunds_od_0", - &cls->order); + &cls->orders[0]); + make_order ("test_refunds_od_1", + &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]); + make_deposit (&cls->instance, + &cls->account, + &cls->orders[1], + &cls->signkey, + &cls->deposits[2]); /* Refund */ make_refund (&cls->deposits[0], - &cls->refund); + &cls->refunds[0]); + make_refund (&cls->deposits[2], + &cls->refunds[1]); + make_refund (&cls->deposits[2], + &cls->refunds[2]); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:10.00", + &cls->refunds[1].refund_amount)); + cls->refunds[1].reason = "refund 1"; + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:10.00", + &cls->refunds[2].refund_amount)); + cls->refunds[2].reason = "refund 2"; /* Refund proof */ GNUNET_assert (GNUNET_OK == @@ -6129,7 +6159,8 @@ static void post_test_refunds (struct TestRefunds_Closure *cls) { free_instance_data (&cls->instance); - free_order_data (&cls->order); + free_order_data (&cls->orders[0]); + free_order_data (&cls->orders[1]); } @@ -6154,11 +6185,11 @@ run_test_refunds (struct TestRefunds_Closure *cls) GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* 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)); /* Insert a signing key */ TEST_RET_ON_FAIL (test_insert_exchange_signkey (&cls->signkey, @@ -6174,41 +6205,42 @@ run_test_refunds (struct TestRefunds_Closure *cls) GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* Mark as paid */ TEST_RET_ON_FAIL (test_mark_contract_paid (&cls->instance, - &cls->order, + &cls->orders[0], GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); /* Test refund coin */ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == plugin->refund_coin (plugin->cls, cls->instance.instance.id, &cls->deposits[0].h_contract_terms, - cls->refund.timestamp, - cls->refund.coin_pub, - cls->refund.reason), + cls->refunds[0].timestamp, + cls->refunds[0].coin_pub, + cls->refunds[0].reason), "Refund coin failed\n"); refund_serial = get_refund_serial (&cls->instance, &cls->deposits[0].h_contract_terms, - &cls->refund); + &cls->refunds[0]); /* Test double refund fails */ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == plugin->refund_coin (plugin->cls, cls->instance.instance.id, &cls->deposits[0].h_contract_terms, - cls->refund.timestamp, - cls->refund.coin_pub, - cls->refund.reason), + cls->refunds[0].timestamp, + cls->refunds[0].coin_pub, + cls->refunds[0].reason), "Refund coin failed\n"); /* Test lookup refunds */ TEST_RET_ON_FAIL (test_lookup_refunds (&cls->instance, &cls->deposits[0].h_contract_terms, 1, - cls->refund.coin_pub, - &cls->refund.refund_amount)); + cls->refunds[0].coin_pub, + &cls->refunds[0].refund_amount)); /* Test lookup refunds detailed */ TEST_RET_ON_FAIL (test_lookup_refunds_detailed (&cls->instance, &cls->deposits[0]. h_contract_terms, + true, 1, - &cls->refund)); + &cls->refunds[0])); /* Test insert refund proof */ TEST_COND_RET_ON_FAIL (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == plugin->insert_refund_proof (plugin->cls, @@ -6231,7 +6263,7 @@ run_test_refunds (struct TestRefunds_Closure *cls) TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_TOO_HIGH == plugin->increase_refund (plugin->cls, cls->instance.instance.id, - cls->order.id, + cls->orders[0].id, &inc, "more"), "Increase refund failed\n"); @@ -6242,7 +6274,7 @@ run_test_refunds (struct TestRefunds_Closure *cls) TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_SUCCESS == plugin->increase_refund (plugin->cls, cls->instance.instance.id, - cls->order.id, + cls->orders[0].id, &inc, "more"), "Increase refund failed\n"); @@ -6250,7 +6282,46 @@ run_test_refunds (struct TestRefunds_Closure *cls) TEST_RET_ON_FAIL (test_lookup_refund_proof (1, &cls->refund_proof.exchange_sig, &cls->signkey.exchange_pub)); - + 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_mark_contract_paid (&cls->instance, + &cls->orders[1], + GNUNET_DB_STATUS_SUCCESS_ONE_RESULT)); + /* Test refunding a small amount of the coin, then increasing it */ + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:10.00", + &inc)); + TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_SUCCESS == + plugin->increase_refund (plugin->cls, + cls->instance.instance.id, + cls->orders[1].id, + &inc, + cls->refunds[1].reason), + "Increase refund failed\n"); + GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:20.00", + &inc)); + TEST_COND_RET_ON_FAIL (TALER_MERCHANTDB_RS_SUCCESS == + plugin->increase_refund (plugin->cls, + cls->instance.instance.id, + cls->orders[1].id, + &inc, + cls->refunds[2].reason), + "Increase refund failed\n"); + TEST_RET_ON_FAIL (test_lookup_refunds_detailed (&cls->instance, + &cls->deposits[2]. + h_contract_terms, + false, + 2, + &cls->refunds[1])); return 0; } -- cgit v1.2.3