diff options
Diffstat (limited to 'src/exchange-lib/test_exchange_api.c')
-rw-r--r-- | src/exchange-lib/test_exchange_api.c | 273 |
1 files changed, 226 insertions, 47 deletions
diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c index b20f7706..49c124c8 100644 --- a/src/exchange-lib/test_exchange_api.c +++ b/src/exchange-lib/test_exchange_api.c @@ -139,12 +139,12 @@ enum OpCode /** * Check that the fakebank has received a certain transaction. */ - OC_CHECK_BANK_DEPOSIT, + OC_CHECK_BANK_TRANSFER, /** * Check that the fakebank has not received any other transactions. */ - OC_CHECK_BANK_DEPOSITS_EMPTY + OC_CHECK_BANK_TRANSFERS_EMPTY }; @@ -514,8 +514,13 @@ struct Command struct TALER_EXCHANGE_WireDepositsHandle *wdh; /** - * Reference to a /deposit/wtid command. If set, we use the - * WTID from that command. + * Reference to a command providing a WTID. If set, we use the + * WTID from that command. The command can be either an + * #OC_DEPOSIT_WTID or an #OC_CHECK_BANK_TRANSFER. In the + * case of the bank transfer, we check that the total amount + * claimed by the exchange matches the total amount transferred + * by the bank. In the case of a /deposit/wtid, we check + * that the wire details match. */ const char *wtid_ref; @@ -524,6 +529,13 @@ struct Command */ struct TALER_WireTransferIdentifierRawP wtid; + /** + * What is the expected total amount? Only used if + * @e expected_response_code was #MHD_HTTP_OK. + */ + const char *total_amount_expected; + + /* TODO: may want to add list of deposits we expected to see aggregated here in the future. */ @@ -545,10 +557,9 @@ struct Command const char *deposit_ref; /** - * What is the expected total amount? Only used if - * @e expected_response_code was #MHD_HTTP_OK. + * Which #OC_CHECK_BANK_TRANSFER wtid should this match? NULL for none. */ - struct TALER_Amount total_amount_expected; + const char *bank_transfer_ref; /** * Wire transfer identifier, set if #MHD_HTTP_OK was the response code. @@ -588,7 +599,7 @@ struct Command */ struct TALER_WireTransferIdentifierRawP wtid; - } check_bank_deposit; + } check_bank_transfer; } details; @@ -625,6 +636,18 @@ struct InterpreterState /** + * Pipe used to communicate child death via signal. + */ +static struct GNUNET_DISK_PipeHandle *sigpipe; + +/** + * ID of task called whenever we get a SIGCHILD. + */ +static struct GNUNET_SCHEDULER_Task *child_death_task; + + + +/** * The testcase failed, return with an error code. * * @param is interpreter state to clean up @@ -1185,6 +1208,30 @@ link_cb (void *cls, /** + * Task triggered whenever we receive a SIGCHLD (child + * process died). + * + * @param cls closure, NULL if we need to self-restart + */ +static void +maint_child_death (void *cls) +{ + struct InterpreterState *is = cls; + struct Command *cmd = &is->commands[is->ip]; + const struct GNUNET_DISK_FileHandle *pr; + char c[16]; + + child_death_task = NULL; + pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); + GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); + GNUNET_OS_process_wait (cmd->details.run_aggregator.aggregator_proc); + GNUNET_OS_process_destroy (cmd->details.run_aggregator.aggregator_proc); + cmd->details.run_aggregator.aggregator_proc = NULL; + next_command (is); +} + + +/** * Find denomination key matching the given amount. * * @param keys array of keys to search @@ -1223,9 +1270,9 @@ find_pk (const struct TALER_EXCHANGE_Keys *keys, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Have denomination key for `%s', but with wrong expiration range %llu vs [%llu,%llu)\n", str, - now.abs_value_us, - pk->valid_from.abs_value_us, - pk->withdraw_valid_until.abs_value_us); + (unsigned long long) now.abs_value_us, + (unsigned long long) pk->valid_from.abs_value_us, + (unsigned long long) pk->withdraw_valid_until.abs_value_us); GNUNET_free (str); return NULL; } @@ -1321,6 +1368,7 @@ wire_deposits_cb (void *cls, struct InterpreterState *is = cls; struct Command *cmd = &is->commands[is->ip]; const struct Command *ref; + struct TALER_Amount expected_amount; cmd->details.wire_deposits.wdh = NULL; if (cmd->expected_response_code != http_status) @@ -1336,42 +1384,82 @@ wire_deposits_cb (void *cls, switch (http_status) { case MHD_HTTP_OK: - ref = find_command (is, - cmd->details.wire_deposits.wtid_ref); - GNUNET_assert (NULL != ref); + if (GNUNET_OK != + TALER_string_to_amount (cmd->details.wire_deposits.total_amount_expected, + &expected_amount)) + { + GNUNET_break (0); + fail (is); + return; + } if (0 != TALER_amount_cmp (total_amount, - &ref->details.deposit_wtid.total_amount_expected)) + &expected_amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Total amount missmatch to command %s\n", - http_status, cmd->label); json_dumpf (json, stderr, 0); fail (is); return; } - if (NULL != ref->details.deposit_wtid.deposit_ref) + ref = find_command (is, + cmd->details.wire_deposits.wtid_ref); + GNUNET_assert (NULL != ref); + switch (ref->oc) { - const struct Command *dep; - struct GNUNET_HashCode hw; - - dep = find_command (is, - ref->details.deposit_wtid.deposit_ref); - GNUNET_assert (NULL != dep); - GNUNET_CRYPTO_hash (dep->details.deposit.wire_details, - strlen (dep->details.deposit.wire_details), - &hw); - if (0 != memcmp (&hw, - h_wire, - sizeof (struct GNUNET_HashCode))) + case OC_DEPOSIT_WTID: + if (NULL != ref->details.deposit_wtid.deposit_ref) + { + const struct Command *dep; + struct GNUNET_HashCode hw; + json_t *wire; + + dep = find_command (is, + ref->details.deposit_wtid.deposit_ref); + GNUNET_assert (NULL != dep); + wire = json_loads (dep->details.deposit.wire_details, + JSON_REJECT_DUPLICATES, + NULL); + TALER_JSON_hash (wire, + &hw); + json_decref (wire); + if (0 != memcmp (&hw, + h_wire, + sizeof (struct GNUNET_HashCode))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Wire hash missmatch to command %s\n", + cmd->label); + json_dumpf (json, stderr, 0); + fail (is); + return; + } + } + break; + case OC_CHECK_BANK_TRANSFER: + if (GNUNET_OK != + TALER_string_to_amount (ref->details.check_bank_transfer.amount, + &expected_amount)) + { + GNUNET_break (0); + fail (is); + return; + } + if (0 != TALER_amount_cmp (total_amount, + &expected_amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Wire hash missmatch to command %s\n", + "Total amount missmatch to command %s\n", cmd->label); json_dumpf (json, stderr, 0); fail (is); return; } + break; + default: + GNUNET_break (0); + fail (is); + return; } break; default: @@ -1421,6 +1509,22 @@ deposit_wtid_cb (void *cls, { case MHD_HTTP_OK: cmd->details.deposit_wtid.wtid = *wtid; + if (NULL != cmd->details.deposit_wtid.bank_transfer_ref) + { + const struct Command *ref; + + ref = find_command (is, + cmd->details.deposit_wtid.bank_transfer_ref); + GNUNET_assert (NULL != ref); + if (0 != memcmp (wtid, + &ref->details.check_bank_transfer.wtid, + sizeof (struct TALER_WireTransferIdentifierRawP))) + { + GNUNET_break (0); + fail (is); + return; + } + } break; default: break; @@ -1698,7 +1802,7 @@ interpreter_run (void *cls) GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.deposit.merchant_priv.eddsa_priv, &merchant_pub.eddsa_pub); - wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS); + wire_deadline = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_ZERO); timestamp = GNUNET_TIME_absolute_get (); GNUNET_TIME_round_abs (×tamp); { @@ -1919,8 +2023,8 @@ interpreter_run (void *cls) case OC_DEPOSIT_WTID: cmd->details.wire_deposits.wtid = ref->details.deposit_wtid.wtid; break; - case OC_CHECK_BANK_DEPOSIT: - cmd->details.wire_deposits.wtid = ref->details.check_bank_deposit.wtid; + case OC_CHECK_BANK_TRANSFER: + cmd->details.wire_deposits.wtid = ref->details.check_bank_transfer.wtid; break; default: GNUNET_break (0); @@ -1999,6 +2103,8 @@ interpreter_run (void *cls) return; case OC_RUN_AGGREGATOR: { + const struct GNUNET_DISK_FileHandle *pr; + cmd->details.run_aggregator.aggregator_proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, @@ -2014,16 +2120,16 @@ interpreter_run (void *cls) fail (is); return; } - GNUNET_OS_process_wait (cmd->details.run_aggregator.aggregator_proc); - GNUNET_OS_process_destroy (cmd->details.run_aggregator.aggregator_proc); - cmd->details.run_aggregator.aggregator_proc = NULL; - next_command (is); + pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ); + child_death_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, + pr, + &maint_child_death, is); return; } - case OC_CHECK_BANK_DEPOSIT: + case OC_CHECK_BANK_TRANSFER: { if (GNUNET_OK != - TALER_string_to_amount (cmd->details.check_bank_deposit.amount, + TALER_string_to_amount (cmd->details.check_bank_transfer.amount, &amount)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -2036,9 +2142,9 @@ interpreter_run (void *cls) if (GNUNET_OK != FAKEBANK_check (fakebank, &amount, - cmd->details.check_bank_deposit.account_debit, - cmd->details.check_bank_deposit.account_credit, - &cmd->details.check_bank_deposit.wtid)) + cmd->details.check_bank_transfer.account_debit, + cmd->details.check_bank_transfer.account_credit, + &cmd->details.check_bank_transfer.wtid)) { GNUNET_break (0); fail (is); @@ -2047,7 +2153,7 @@ interpreter_run (void *cls) next_command (is); return; } - case OC_CHECK_BANK_DEPOSITS_EMPTY: + case OC_CHECK_BANK_TRANSFERS_EMPTY: { if (GNUNET_OK != FAKEBANK_check_empty (fakebank)) @@ -2072,6 +2178,24 @@ interpreter_run (void *cls) /** + * Signal handler called for SIGCHLD. Triggers the + * respective handler by writing to the trigger pipe. + */ +static void +sighandler_child_death () +{ + static char c; + int old_errno = errno; /* back-up errno */ + + GNUNET_break (1 == + GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle + (sigpipe, GNUNET_DISK_PIPE_END_WRITE), + &c, sizeof (c))); + errno = old_errno; /* restore errno */ +} + + +/** * Function run when the test terminates (good or bad) with timeout. * * @param cls NULL @@ -2251,9 +2375,9 @@ do_shutdown (void *cls) cmd->details.run_aggregator.aggregator_proc = NULL; } break; - case OC_CHECK_BANK_DEPOSIT: + case OC_CHECK_BANK_TRANSFER: break; - case OC_CHECK_BANK_DEPOSITS_EMPTY: + case OC_CHECK_BANK_TRANSFERS_EMPTY: break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -2526,7 +2650,7 @@ run (void *cls) .details.deposit.amount = "EUR:0.1", .details.deposit.coin_ref = "refresh-reveal-1", .details.deposit.coin_idx = 4, - .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":42 }", + .details.deposit.wire_details = "{ \"type\":\"test\", \"bank_uri\":\"http://localhost:8082/\", \"account_number\":43 }", .details.deposit.contract = "{ \"items\": [ { \"name\":\"ice cream\", \"value\":3 } ] }", .details.deposit.transaction_id = 2 }, @@ -2563,12 +2687,59 @@ run (void *cls) .label = "wire-deposit-failing", .expected_response_code = MHD_HTTP_NOT_FOUND }, + /* Run transfers. Note that _actual_ aggregation will NOT + happen here, as each deposit operation is run with a + fresh merchant public key! */ { .oc = OC_RUN_AGGREGATOR, .label = "run-aggregator" }, - { .oc = OC_CHECK_BANK_DEPOSITS_EMPTY, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-499c", + .details.check_bank_transfer.amount = "EUR:4.99", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 42 + }, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-99c1", + .details.check_bank_transfer.amount = "EUR:0.99", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 42 + }, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-99c2", + .details.check_bank_transfer.amount = "EUR:0.99", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 42 + }, + { .oc = OC_CHECK_BANK_TRANSFER, + .label = "check_bank_transfer-9c", + .details.check_bank_transfer.amount = "EUR:0.09", + .details.check_bank_transfer.account_debit = 2, + .details.check_bank_transfer.account_credit = 43 + }, + + { .oc = OC_CHECK_BANK_TRANSFERS_EMPTY, .label = "check_bank_empty" }, + { .oc = OC_DEPOSIT_WTID, + .label = "deposit-wtid-ok", + .expected_response_code = MHD_HTTP_OK, + .details.deposit_wtid.deposit_ref = "deposit-simple", + .details.deposit_wtid.bank_transfer_ref = "check_bank_transfer-499c" }, + + { .oc = OC_WIRE_DEPOSITS, + .label = "wire-deposits-sucess-bank", + .expected_response_code = MHD_HTTP_OK, + .details.wire_deposits.wtid_ref = "check_bank_transfer-99c1", + .details.wire_deposits.total_amount_expected = "EUR:0.99" }, + + { .oc = OC_WIRE_DEPOSITS, + .label = "wire-deposits-sucess-wtid", + .expected_response_code = MHD_HTTP_OK, + .details.wire_deposits.wtid_ref = "deposit-wtid-ok", + .details.wire_deposits.total_amount_expected = "EUR:4.99" }, + + /* TODO: trigger aggregation logic and then check the cases where tracking succeeds! */ @@ -2613,6 +2784,7 @@ main (int argc, { struct GNUNET_OS_Process *proc; struct GNUNET_OS_Process *exchanged; + struct GNUNET_SIGNAL_Context *shc_chld; GNUNET_log_setup ("test-exchange-api", "WARNING", @@ -2646,7 +2818,14 @@ main (int argc, while (0 != system ("wget -q -t 1 -T 1 http://127.0.0.1:8081/keys -o /dev/null -O /dev/null")); fprintf (stderr, "\n"); result = GNUNET_SYSERR; + sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); + GNUNET_assert (NULL != sigpipe); + shc_chld = GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, + &sighandler_child_death); GNUNET_SCHEDULER_run (&run, NULL); + GNUNET_SIGNAL_handler_uninstall (shc_chld); + shc_chld = NULL; + GNUNET_DISK_pipe_close (sigpipe); GNUNET_OS_process_kill (exchanged, SIGTERM); GNUNET_OS_process_wait (exchanged); |