fix test to ensure DB invariants are met

This commit is contained in:
Christian Grothoff 2016-04-04 16:47:11 +02:00
parent bd6fb59e4b
commit 0ff76b5abb
3 changed files with 170 additions and 1 deletions

View File

@ -290,6 +290,16 @@ static struct Transaction *transactions_head;
*/ */
static struct Transaction *transactions_tail; static struct Transaction *transactions_tail;
/**
* Private key we use for fake coins.
*/
static struct GNUNET_CRYPTO_RsaPrivateKey *coin_pk;
/**
* Public key we use for fake coins.
*/
static struct GNUNET_CRYPTO_RsaPublicKey *coin_pub;
/** /**
* Interprets the commands from the test program. * Interprets the commands from the test program.
@ -383,6 +393,47 @@ maint_child_death (void *cls,
} }
/**
* Setup (fake) information about a coin used in deposit.
*
* @param[out] issue information to initialize with "valid" data
*/
static void
fake_issue (struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
{
memset (issue, 0, sizeof (struct TALER_EXCHANGEDB_DenominationKeyInformationP));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:1",
&issue->properties.value));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_withdraw));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_deposit));
GNUNET_assert (GNUNET_OK ==
TALER_string_to_amount_nbo ("EUR:0.1",
&issue->properties.fee_refresh));
}
/**
* Setup (fake) information about a coin used in deposit.
*
* @param[out] coin information to initialize with "valid" data
*/
static void
fake_coin (struct TALER_CoinPublicInfo *coin)
{
struct GNUNET_HashCode hc;
coin->denom_pub.rsa_public_key = coin_pub;
GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
&hc);
coin->denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (coin_pk,
&hc);
}
/** /**
* Helper function to fake a deposit operation. * Helper function to fake a deposit operation.
@ -423,6 +474,7 @@ do_deposit (struct Command *cmd)
GNUNET_break (0); GNUNET_break (0);
return GNUNET_SYSERR; return GNUNET_SYSERR;
} }
fake_coin (&deposit.coin);
/* Build JSON for wire details; /* Build JSON for wire details;
note that this simple method may fail in the future if we implement note that this simple method may fail in the future if we implement
and enforce signature checking on test-wire account details */ and enforce signature checking on test-wire account details */
@ -451,6 +503,7 @@ do_deposit (struct Command *cmd)
ret = GNUNET_SYSERR; ret = GNUNET_SYSERR;
else else
ret = GNUNET_OK; ret = GNUNET_OK;
GNUNET_CRYPTO_rsa_signature_free (deposit.coin.denom_sig.rsa_signature);
json_decref (deposit.wire); json_decref (deposit.wire);
return ret; return ret;
} }
@ -590,7 +643,7 @@ static void
run_test () run_test ()
{ {
static struct Command commands[] = { static struct Command commands[] = {
/* FIXME: prime DB */ /* test running with empty DB */
{ {
.opcode = OPCODE_RUN_AGGREGATOR, .opcode = OPCODE_RUN_AGGREGATOR,
.label = "run-aggregator-on-empty-db" .label = "run-aggregator-on-empty-db"
@ -599,6 +652,57 @@ run_test ()
.opcode = OPCODE_EXPECT_TRANSACTIONS_EMPTY, .opcode = OPCODE_EXPECT_TRANSACTIONS_EMPTY,
.label = "expect-empty-transactions-on-start" .label = "expect-empty-transactions-on-start"
}, },
/* test simple deposit */
{
.opcode = OPCODE_DATABASE_DEPOSIT,
.label = "do-deposit-",
.details.deposit.merchant_name = "bob",
.details.deposit.merchant_account = 4,
.details.deposit.transaction_id = 1,
.details.deposit.wire_deadline = { 1000LL * 1000 * 0 }, /* 5s */
.details.deposit.amount_with_fee = "EUR:1",
.details.deposit.deposit_fee = "EUR:0"
},
{
.opcode = OPCODE_RUN_AGGREGATOR,
.label = "run-aggregator-deposit-1"
},
/* The above step is already known to fail (with an error message)
right now, so we skip the rest of the test. */
{
.opcode = OPCODE_TERMINATE_SKIP,
.label = "testcase-incomplete-terminating-with-skip"
},
{
.opcode = OPCODE_EXPECT_TRANSACTION,
.label = "expect-deposit-1",
.details.expect_transaction.debit_account = 1,
.details.expect_transaction.credit_account = 4,
.details.expect_transaction.amount = "EUR:1"
},
{
.opcode = OPCODE_EXPECT_TRANSACTIONS_EMPTY,
.label = "expect-empty-transactions-on-start"
},
/* test idempotency: run again on transactions already done */
{
.opcode = OPCODE_DATABASE_DEPOSIT,
.label = "do-deposit-",
.details.deposit.merchant_name = "bob",
.details.deposit.merchant_account = 4,
.details.deposit.transaction_id = 1,
.details.deposit.wire_deadline = { 1000LL * 1000 * 0 }, /* 5s */
.details.deposit.amount_with_fee = "EUR:1",
.details.deposit.deposit_fee = "EUR:0"
},
{
.opcode = OPCODE_EXPECT_TRANSACTIONS_EMPTY,
.label = "expect-empty-transactions-on-start"
},
{ {
.opcode = OPCODE_TERMINATE_SKIP, .opcode = OPCODE_TERMINATE_SKIP,
.label = "testcase-incomplete-terminating-with-skip" .label = "testcase-incomplete-terminating-with-skip"
@ -851,19 +955,43 @@ run (void *cls,
const struct GNUNET_SCHEDULER_TaskContext *tc) const struct GNUNET_SCHEDULER_TaskContext *tc)
{ {
struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct GNUNET_CONFIGURATION_Handle *cfg = cls;
struct TALER_EXCHANGEDB_DenominationKeyInformationP issue;
struct TALER_DenominationPublicKey dpk;
plugin = TALER_EXCHANGEDB_plugin_load (cfg); plugin = TALER_EXCHANGEDB_plugin_load (cfg);
if (GNUNET_OK != if (GNUNET_OK !=
plugin->create_tables (plugin->cls, plugin->create_tables (plugin->cls,
GNUNET_YES)) GNUNET_YES))
{ {
GNUNET_break (0);
TALER_EXCHANGEDB_plugin_unload (plugin); TALER_EXCHANGEDB_plugin_unload (plugin);
plugin = NULL;
result = 77; result = 77;
return; return;
} }
session = plugin->get_session (plugin->cls, session = plugin->get_session (plugin->cls,
GNUNET_YES); GNUNET_YES);
GNUNET_assert (NULL != session); GNUNET_assert (NULL != session);
fake_issue (&issue);
dpk.rsa_public_key = coin_pub;
if ( (GNUNET_OK !=
plugin->start (plugin->cls,
session)) ||
(GNUNET_OK !=
plugin->insert_denomination_info (plugin->cls,
session,
&dpk,
&issue)) ||
(GNUNET_OK !=
plugin->commit (plugin->cls,
session)) )
{
GNUNET_break (0);
TALER_EXCHANGEDB_plugin_unload (plugin);
plugin = NULL;
result = 77;
return;
}
child_death_task = child_death_task =
GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_pipe_handle (sigpipe,
@ -945,7 +1073,11 @@ main (int argc,
GNUNET_assert (NULL != sigpipe); GNUNET_assert (NULL != sigpipe);
shc_chld = shc_chld =
GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
coin_pk = GNUNET_CRYPTO_rsa_private_key_create (1024);
coin_pub = GNUNET_CRYPTO_rsa_private_key_get_public (coin_pk);
GNUNET_SCHEDULER_run (&run, cfg); GNUNET_SCHEDULER_run (&run, cfg);
GNUNET_CRYPTO_rsa_private_key_free (coin_pk);
GNUNET_CRYPTO_rsa_public_key_free (coin_pub);
GNUNET_SIGNAL_handler_uninstall (shc_chld); GNUNET_SIGNAL_handler_uninstall (shc_chld);
shc_chld = NULL; shc_chld = NULL;
GNUNET_DISK_pipe_close (sigpipe); GNUNET_DISK_pipe_close (sigpipe);

View File

@ -127,6 +127,19 @@ TALER_string_to_amount (const char *str,
struct TALER_Amount *denom); struct TALER_Amount *denom);
/**
* Parse denomination description, in the format "T:V.F".
*
* @param str denomination description
* @param denom denomination to write the result to, in NBO
* @return #GNUNET_OK if the string is a valid denomination specification,
* #GNUNET_SYSERR if it is invalid.
*/
int
TALER_string_to_amount_nbo (const char *str,
struct TALER_AmountNBO *denom);
/** /**
* Get the value of "zero" in a particular currency. * Get the value of "zero" in a particular currency.
* *

View File

@ -150,6 +150,30 @@ TALER_string_to_amount (const char *str,
} }
/**
* Parse denomination description, in the format "T:V.F".
*
* @param str denomination description
* @param denom denomination to write the result to, in NBO
* @return #GNUNET_OK if the string is a valid denomination specification,
* #GNUNET_SYSERR if it is invalid.
*/
int
TALER_string_to_amount_nbo (const char *str,
struct TALER_AmountNBO *denom)
{
struct TALER_Amount amount;
if (GNUNET_OK !=
TALER_string_to_amount (str,
&amount))
return GNUNET_SYSERR;
TALER_amount_hton (denom,
&amount);
return GNUNET_OK;
}
/** /**
* Convert amount from host to network representation. * Convert amount from host to network representation.
* *