testing refund, fixing bugs, refund test passes

This commit is contained in:
Christian Grothoff 2016-05-21 19:22:03 +02:00
parent 9160245167
commit 8dfb3b87b4
7 changed files with 102 additions and 24 deletions

View File

@ -19,6 +19,9 @@ Use the configuration and other resources for the exchange to operate from DIRNA
.IP "\-h, \-\-help" .IP "\-h, \-\-help"
Print short help on options. Print short help on options.
.B .B
.IP "\-r, \-\-reset"
Drop tables. Dangerous, will delete all existing data in the database before creating the tables.
.B
.IP "\-v, \-\-version" .IP "\-v, \-\-version"
Print version information. Print version information.

View File

@ -169,6 +169,10 @@ handle_refund_finished (void *cls,
/* Nothing really to verify, this should never /* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */ happen, we should pass the JSON reply to the application */
break; break;
case MHD_HTTP_GONE:
/* Kind of normal: the money was already sent to the merchant
(it was too late for the refund). */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR: case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API /* Server had an internal issue; we should retry, but this API
leaves this to the application */ leaves this to the application */
@ -266,7 +270,7 @@ TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange,
" s:I, s:I," /* transaction id, rtransaction id */ " s:I, s:I," /* transaction id, rtransaction id */
" s:o, s:o}", /* merchant_pub, merchant_sig */ " s:o, s:o}", /* merchant_pub, merchant_sig */
"refund_amount", TALER_JSON_from_amount (amount), "refund_amount", TALER_JSON_from_amount (amount),
"refund_fee", TALER_JSON_from_amount (amount), "refund_fee", TALER_JSON_from_amount (refund_fee),
"H_contract", GNUNET_JSON_from_data_auto (h_contract), "H_contract", GNUNET_JSON_from_data_auto (h_contract),
"coin_pub", GNUNET_JSON_from_data_auto (coin_pub), "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
"transaction_id", (json_int_t) transaction_id, "transaction_id", (json_int_t) transaction_id,

View File

@ -2926,7 +2926,10 @@ run (void *cls)
}, },
/* Run transfers. Should do nothing as refund deadline blocks it */ /* Run transfers. Should do nothing as refund deadline blocks it */
{ .oc = OC_RUN_AGGREGATOR, { .oc = OC_RUN_AGGREGATOR,
.label = "run-aggregator" }, .label = "run-aggregator-refund" },
/* check that aggregator didn't do anything, as expected */
{ .oc = OC_CHECK_BANK_TRANSFERS_EMPTY,
.label = "check-refund-not-run" },
/* Trigger refund */ /* Trigger refund */
{ .oc = OC_REFUND, { .oc = OC_REFUND,
.label = "refund-ok", .label = "refund-ok",
@ -2949,11 +2952,18 @@ run (void *cls)
}, },
/* Run transfers. This will do the transfer as refund deadline was 0 */ /* Run transfers. This will do the transfer as refund deadline was 0 */
{ .oc = OC_RUN_AGGREGATOR, { .oc = OC_RUN_AGGREGATOR,
.label = "run-aggregator" }, .label = "run-aggregator-3" },
/* Check that deposit did run */
{ .oc = OC_CHECK_BANK_TRANSFER,
.label = "check_bank_transfer-pre-refund",
.details.check_bank_transfer.amount = "EUR:4.98",
.details.check_bank_transfer.account_debit = 2,
.details.check_bank_transfer.account_credit = 42
},
/* Run failing refund, as past deadline & aggregation */ /* Run failing refund, as past deadline & aggregation */
{ .oc = OC_REFUND, { .oc = OC_REFUND,
.label = "refund-fail", .label = "refund-fail",
.expected_response_code = MHD_HTTP_OK, .expected_response_code = MHD_HTTP_GONE,
.details.refund.amount = "EUR:4.99", .details.refund.amount = "EUR:4.99",
.details.refund.fee = "EUR:0.01", .details.refund.fee = "EUR:0.01",
.details.refund.deposit_ref = "deposit-refund-2", .details.refund.deposit_ref = "deposit-refund-2",
@ -3015,6 +3025,16 @@ main (int argc,
NULL); NULL);
GNUNET_OS_process_wait (proc); GNUNET_OS_process_wait (proc);
GNUNET_OS_process_destroy (proc); GNUNET_OS_process_destroy (proc);
proc = GNUNET_OS_start_process (GNUNET_NO,
GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL,
"taler-exchange-dbinit",
"taler-exchange-dbinit",
"-c", "test_exchange_api.conf",
"-r",
NULL);
GNUNET_OS_process_wait (proc);
GNUNET_OS_process_destroy (proc);
exchanged = GNUNET_OS_start_process (GNUNET_NO, exchanged = GNUNET_OS_start_process (GNUNET_NO,
GNUNET_OS_INHERIT_STD_ALL, GNUNET_OS_INHERIT_STD_ALL,
NULL, NULL, NULL, NULL, NULL, NULL,

View File

@ -23,12 +23,16 @@
#include "taler_exchangedb_plugin.h" #include "taler_exchangedb_plugin.h"
/** /**
* Return value from main(). * Return value from main().
*/ */
static int global_ret; static int global_ret;
/**
* -r option: do full DB reset
*/
static int reset_db;
/** /**
* Main function that will be run. * Main function that will be run.
* *
@ -53,6 +57,8 @@ run (void *cls,
global_ret = 1; global_ret = 1;
return; return;
} }
if (reset_db)
(void) plugin->drop_tables (plugin->cls);
if (GNUNET_OK != if (GNUNET_OK !=
plugin->create_tables (plugin->cls)) plugin->create_tables (plugin->cls))
{ {
@ -79,6 +85,9 @@ main (int argc,
char *const *argv) char *const *argv)
{ {
const struct GNUNET_GETOPT_CommandLineOption options[] = { const struct GNUNET_GETOPT_CommandLineOption options[] = {
{'r', "reset", NULL,
"reset database (DANGEROUS: all existing data is lost!)", 0,
&GNUNET_GETOPT_set_one, &reset_db},
GNUNET_GETOPT_OPTION_END GNUNET_GETOPT_OPTION_END
}; };

View File

@ -340,11 +340,13 @@ TMH_DB_execute_refund (struct MHD_Connection *connection,
MHD_HTTP_NOT_FOUND); MHD_HTTP_NOT_FOUND);
} }
deposit_found = GNUNET_NO; deposit_found = GNUNET_NO;
refund_found = GNUNET_NO;
for (tlp = tl; NULL != tlp; tlp = tlp->next) for (tlp = tl; NULL != tlp; tlp = tlp->next)
{ {
switch (tlp->type) switch (tlp->type)
{ {
case TALER_EXCHANGEDB_TT_DEPOSIT: case TALER_EXCHANGEDB_TT_DEPOSIT:
if (GNUNET_NO == deposit_found)
{ {
dep = tlp->details.deposit; dep = tlp->details.deposit;
if ( (0 == memcmp (&dep->merchant_pub, if ( (0 == memcmp (&dep->merchant_pub,
@ -364,6 +366,7 @@ TMH_DB_execute_refund (struct MHD_Connection *connection,
/* Melts cannot be refunded, ignore here */ /* Melts cannot be refunded, ignore here */
break; break;
case TALER_EXCHANGEDB_TT_REFUND: case TALER_EXCHANGEDB_TT_REFUND:
if (GNUNET_NO == refund_found)
{ {
ref = tlp->details.refund; ref = tlp->details.refund;
/* First, check if existing refund request is identical */ /* First, check if existing refund request is identical */
@ -476,15 +479,13 @@ TMH_DB_execute_refund (struct MHD_Connection *connection,
MHD_HTTP_GONE); MHD_HTTP_GONE);
} }
/* We no longer need 'tl' or 'dep' or 'ref' */
TMH_plugin->free_coin_transaction_list (TMH_plugin->cls,
tl);
/* check refund amount is sufficiently low */ /* check refund amount is sufficiently low */
if (1 == TALER_amount_cmp (&refund->refund_amount, if (1 == TALER_amount_cmp (&refund->refund_amount,
&dep->amount_with_fee) ) &dep->amount_with_fee) )
{ {
GNUNET_break_op (0); /* cannot refund more than original value */ GNUNET_break_op (0); /* cannot refund more than original value */
TMH_plugin->free_coin_transaction_list (TMH_plugin->cls,
tl);
return TMH_RESPONSE_reply_refund_failure (connection, return TMH_RESPONSE_reply_refund_failure (connection,
MHD_HTTP_PRECONDITION_FAILED); MHD_HTTP_PRECONDITION_FAILED);
} }
@ -500,6 +501,8 @@ TMH_DB_execute_refund (struct MHD_Connection *connection,
not good... */ not good... */
GNUNET_break (0); GNUNET_break (0);
TMH_KS_release (mks); TMH_KS_release (mks);
TMH_plugin->free_coin_transaction_list (TMH_plugin->cls,
tl);
return TMH_RESPONSE_reply_internal_error (connection, return TMH_RESPONSE_reply_internal_error (connection,
"denomination key not found"); "denomination key not found");
} }
@ -513,6 +516,8 @@ TMH_DB_execute_refund (struct MHD_Connection *connection,
{ {
TMH_plugin->rollback (TMH_plugin->cls, TMH_plugin->rollback (TMH_plugin->cls,
session); session);
TMH_plugin->free_coin_transaction_list (TMH_plugin->cls,
tl);
return TMH_RESPONSE_reply_arg_invalid (connection, return TMH_RESPONSE_reply_arg_invalid (connection,
"refund_fee"); "refund_fee");
} }
@ -521,6 +526,8 @@ TMH_DB_execute_refund (struct MHD_Connection *connection,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Refund fee proposed by merchant is higher than necessary.\n"); "Refund fee proposed by merchant is higher than necessary.\n");
} }
TMH_plugin->free_coin_transaction_list (TMH_plugin->cls,
tl);
/* Finally, store new refund data */ /* Finally, store new refund data */
if (GNUNET_OK != if (GNUNET_OK !=

View File

@ -50,18 +50,18 @@ static int
verify_and_execute_refund (struct MHD_Connection *connection, verify_and_execute_refund (struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_Refund *refund) const struct TALER_EXCHANGEDB_Refund *refund)
{ {
struct TALER_RefundRequestPS dr; struct TALER_RefundRequestPS rr;
dr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND); rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
dr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS)); rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
dr.h_contract = refund->h_contract; rr.h_contract = refund->h_contract;
dr.transaction_id = GNUNET_htonll (refund->transaction_id); rr.transaction_id = GNUNET_htonll (refund->transaction_id);
dr.coin_pub = refund->coin.coin_pub; rr.coin_pub = refund->coin.coin_pub;
dr.merchant = refund->merchant_pub; rr.merchant = refund->merchant_pub;
dr.rtransaction_id = GNUNET_htonll (refund->rtransaction_id); rr.rtransaction_id = GNUNET_htonll (refund->rtransaction_id);
TALER_amount_hton (&dr.refund_amount, TALER_amount_hton (&rr.refund_amount,
&refund->refund_amount); &refund->refund_amount);
TALER_amount_hton (&dr.refund_fee, TALER_amount_hton (&rr.refund_fee,
&refund->refund_fee); &refund->refund_fee);
if (GNUNET_YES != if (GNUNET_YES !=
TALER_amount_cmp_currency (&refund->refund_amount, TALER_amount_cmp_currency (&refund->refund_amount,
@ -80,7 +80,7 @@ verify_and_execute_refund (struct MHD_Connection *connection,
} }
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND, GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
&dr.purpose, &rr.purpose,
&refund->merchant_sig.eddsa_sig, &refund->merchant_sig.eddsa_sig,
&refund->merchant_pub.eddsa_pub)) &refund->merchant_pub.eddsa_pub))
{ {

View File

@ -2260,12 +2260,17 @@ postgres_test_deposit_done (void *cls,
PQclear (result); PQclear (result);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
if (1 != PQntuples (result))
{
GNUNET_break (0);
PQclear (result);
return GNUNET_SYSERR;
}
{ {
/* NOTE: maybe wrong type for a 'boolean' */ uint8_t done = 0;
uint32_t done = 0;
struct GNUNET_PQ_ResultSpec rs[] = { struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_uint32 ("done", GNUNET_PQ_result_spec_auto_from_type ("done",
&done), &done),
GNUNET_PQ_result_spec_end GNUNET_PQ_result_spec_end
}; };
@ -3703,6 +3708,16 @@ postgres_get_coin_transactions (void *cls,
tl->next = head; tl->next = head;
tl->type = TALER_EXCHANGEDB_TT_DEPOSIT; tl->type = TALER_EXCHANGEDB_TT_DEPOSIT;
tl->details.deposit = deposit; tl->details.deposit = deposit;
if (GNUNET_SYSERR == get_known_coin (cls,
session,
&deposit->coin.coin_pub,
&deposit->coin))
{
GNUNET_break (0);
GNUNET_free (deposit);
PQclear (result);
goto cleanup;
}
head = tl; head = tl;
continue; continue;
} }
@ -3762,6 +3777,16 @@ postgres_get_coin_transactions (void *cls,
tl->next = head; tl->next = head;
tl->type = TALER_EXCHANGEDB_TT_REFRESH_MELT; tl->type = TALER_EXCHANGEDB_TT_REFRESH_MELT;
tl->details.melt = melt; tl->details.melt = melt;
if (GNUNET_SYSERR == get_known_coin (cls,
session,
coin_pub,
&melt->coin))
{
GNUNET_break (0);
GNUNET_free (melt);
PQclear (result);
goto cleanup;
}
head = tl; head = tl;
continue; continue;
} }
@ -3826,6 +3851,16 @@ postgres_get_coin_transactions (void *cls,
tl->next = head; tl->next = head;
tl->type = TALER_EXCHANGEDB_TT_REFUND; tl->type = TALER_EXCHANGEDB_TT_REFUND;
tl->details.refund = refund; tl->details.refund = refund;
if (GNUNET_SYSERR == get_known_coin (cls,
session,
coin_pub,
&refund->coin))
{
GNUNET_break (0);
GNUNET_free (refund);
PQclear (result);
goto cleanup;
}
head = tl; head = tl;
continue; continue;
} }