aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2016-05-02 08:46:17 +0200
committerChristian Grothoff <christian@grothoff.org>2016-05-02 08:46:17 +0200
commit31ad6aaf116d00cafa29efe659c3076da0d09692 (patch)
tree0e9b3a36911706d94928a7089b45d6cadb6e0b50 /src
parent5fd6a25c6d88c62af9fda04f92b954bb1dbb4436 (diff)
separate interpreter from the rest of the test logic
Diffstat (limited to 'src')
-rw-r--r--src/bank-lib/Makefile.am1
-rw-r--r--src/bank-lib/test_bank_api.c402
-rw-r--r--src/bank-lib/test_bank_interpreter.c349
-rw-r--r--src/bank-lib/test_bank_interpreter.h127
4 files changed, 488 insertions, 391 deletions
diff --git a/src/bank-lib/Makefile.am b/src/bank-lib/Makefile.am
index e833c533c..fe910fa85 100644
--- a/src/bank-lib/Makefile.am
+++ b/src/bank-lib/Makefile.am
@@ -53,6 +53,7 @@ TESTS = \
$(check_PROGRAMS)
test_bank_api_SOURCES = \
+ test_bank_interpreter.c test_bank_interpreter.h \
test_bank_api.c
test_bank_api_LDADD = \
libtalerbank.la \
diff --git a/src/bank-lib/test_bank_api.c b/src/bank-lib/test_bank_api.c
index 7d1bebb8a..6e8f2005b 100644
--- a/src/bank-lib/test_bank_api.c
+++ b/src/bank-lib/test_bank_api.c
@@ -15,7 +15,7 @@
*/
/**
* @file bank/test_bank_api.c
- * @brief testcase to test bank's HTTP API interface
+ * @brief testcase to test bank's HTTP API interface against the "real" bank
* @author Christian Grothoff
*/
#include "platform.h"
@@ -25,378 +25,7 @@
#include <gnunet/gnunet_util_lib.h>
#include <gnunet/gnunet_curl_lib.h>
#include <microhttpd.h>
-
-
-/**
- * Main execution context for the main loop.
- */
-static struct GNUNET_CURL_Context *ctx;
-
-/**
- * Task run on timeout.
- */
-static struct GNUNET_SCHEDULER_Task *timeout_task;
-
-/**
- * Context for running the main loop with GNUnet's SCHEDULER API.
- */
-static struct GNUNET_CURL_RescheduleContext *rc;
-
-/**
- * Result of the testcases, #GNUNET_OK on success
- */
-static int result;
-
-
-/**
- * Opcodes for the interpreter.
- */
-enum OpCode
-{
- /**
- * Termination code, stops the interpreter loop (with success).
- */
- OC_END = 0,
-
- /**
- * Add funds to a reserve by (faking) incoming wire transfer.
- */
- OC_ADMIN_ADD_INCOMING
-
-};
-
-
-/**
- * Details for a bank operation to execute.
- */
-struct Command
-{
- /**
- * Opcode of the command.
- */
- enum OpCode oc;
-
- /**
- * Label for the command, can be NULL.
- */
- const char *label;
-
- /**
- * Which response code do we expect for this command?
- */
- unsigned int expected_response_code;
-
- /**
- * Details about the command.
- */
- union
- {
-
- /**
- * Information for a #OC_ADMIN_ADD_INCOMING command.
- */
- struct
- {
-
- /**
- * String describing the amount to add to the reserve.
- */
- const char *amount;
-
- /**
- * Credited account number.
- */
- uint64_t credit_account_no;
-
- /**
- * Debited account number.
- */
- uint64_t debit_account_no;
-
- /**
- * Wire transfer identifier to use. Initialized to
- * a random value.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Set to the API's handle during the operation.
- */
- struct TALER_BANK_AdminAddIncomingHandle *aih;
-
- } admin_add_incoming;
-
- } details;
-
-};
-
-
-/**
- * State of the interpreter loop.
- */
-struct InterpreterState
-{
- /**
- * Keys from the bank.
- */
- const struct TALER_BANK_Keys *keys;
-
- /**
- * Commands the interpreter will run.
- */
- struct Command *commands;
-
- /**
- * Interpreter task (if one is scheduled).
- */
- struct GNUNET_SCHEDULER_Task *task;
-
- /**
- * Instruction pointer. Tells #interpreter_run() which
- * instruction to run next.
- */
- unsigned int ip;
-
-};
-
-
-/**
- * The testcase failed, return with an error code.
- *
- * @param is interpreter state to clean up
- */
-static void
-fail (struct InterpreterState *is)
-{
- result = GNUNET_SYSERR;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-#if 0
-/**
- * Find a command by label.
- *
- * @param is interpreter state to search
- * @param label label to look for
- * @return NULL if command was not found
- */
-static const struct Command *
-find_command (const struct InterpreterState *is,
- const char *label)
-{
- unsigned int i;
- const struct Command *cmd;
-
- if (NULL == label)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Attempt to lookup command for empty label\n");
- return NULL;
- }
- for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
- if ( (NULL != cmd->label) &&
- (0 == strcmp (cmd->label,
- label)) )
- return cmd;
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command not found: %s\n",
- label);
- return NULL;
-}
-#endif
-
-
-/**
- * Run the main interpreter loop that performs bank operations.
- *
- * @param cls contains the `struct InterpreterState`
- */
-static void
-interpreter_run (void *cls);
-
-
-/**
- * Function called upon completion of our /admin/add/incoming request.
- *
- * @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
- * 0 if the bank's reply is bogus (fails to follow the protocol)
- * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
- */
-static void
-add_incoming_cb (void *cls,
- unsigned int http_status,
- const json_t *json)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
-
- cmd->details.admin_add_incoming.aih = NULL;
- if (cmd->expected_response_code != http_status)
- {
- GNUNET_break (0);
- if (NULL != json)
- {
- fprintf (stderr,
- "Unexpected response code %u:\n",
- http_status);
- json_dumpf (json, stderr, 0);
- fprintf (stderr, "\n");
- }
- fail (is);
- return;
- }
- is->ip++;
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
-}
-
-
-/**
- * Run the main interpreter loop that performs bank operations.
- *
- * @param cls contains the `struct InterpreterState`
- */
-static void
-interpreter_run (void *cls)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd = &is->commands[is->ip];
- struct TALER_Amount amount;
- const struct GNUNET_SCHEDULER_TaskContext *tc;
-
- is->task = NULL;
- tc = GNUNET_SCHEDULER_get_task_context ();
- if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
- {
- fprintf (stderr,
- "Test aborted by shutdown request\n");
- fail (is);
- return;
- }
- switch (cmd->oc)
- {
- case OC_END:
- result = GNUNET_OK;
- GNUNET_SCHEDULER_shutdown ();
- return;
- case OC_ADMIN_ADD_INCOMING:
-
- if (GNUNET_OK !=
- TALER_string_to_amount (cmd->details.admin_add_incoming.amount,
- &amount))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to parse amount `%s' at %u\n",
- cmd->details.admin_add_incoming.amount,
- is->ip);
- fail (is);
- return;
- }
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
- &cmd->details.admin_add_incoming.wtid,
- sizeof (cmd->details.admin_add_incoming.wtid));
- cmd->details.admin_add_incoming.aih
- = TALER_BANK_admin_add_incoming (ctx,
- "http://localhost:8081",
- &cmd->details.admin_add_incoming.wtid,
- &amount,
- cmd->details.admin_add_incoming.debit_account_no,
- cmd->details.admin_add_incoming.credit_account_no,
- &add_incoming_cb,
- is);
- if (NULL == cmd->details.admin_add_incoming.aih)
- {
- GNUNET_break (0);
- fail (is);
- return;
- }
- return;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown instruction %d at %u (%s)\n",
- cmd->oc,
- is->ip,
- cmd->label);
- fail (is);
- return;
- }
-}
-
-
-/**
- * Function run on timeout.
- *
- * @param cls NULL
- */
-static void
-do_timeout (void *cls)
-{
- timeout_task = NULL;
- GNUNET_SCHEDULER_shutdown ();
-}
-
-
-/**
- * Function run when the test terminates (good or bad).
- * Cleans up our state.
- *
- * @param cls the interpreter state.
- */
-static void
-do_shutdown (void *cls)
-{
- struct InterpreterState *is = cls;
- struct Command *cmd;
- unsigned int i;
-
- if (NULL != timeout_task)
- {
- GNUNET_SCHEDULER_cancel (timeout_task);
- timeout_task = NULL;
- }
-
- for (i=0;OC_END != (cmd = &is->commands[i])->oc;i++)
- {
- switch (cmd->oc)
- {
- case OC_END:
- GNUNET_assert (0);
- break;
- case OC_ADMIN_ADD_INCOMING:
- if (NULL != cmd->details.admin_add_incoming.aih)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command %u (%s) did not complete\n",
- i,
- cmd->label);
- TALER_BANK_admin_add_incoming_cancel (cmd->details.admin_add_incoming.aih);
- cmd->details.admin_add_incoming.aih = NULL;
- }
- break;
- default:
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unknown instruction %d at %u (%s)\n",
- cmd->oc,
- i,
- cmd->label);
- break;
- }
- }
- if (NULL != is->task)
- {
- GNUNET_SCHEDULER_cancel (is->task);
- is->task = NULL;
- }
- GNUNET_free (is);
- if (NULL != ctx)
- {
- GNUNET_CURL_fini (ctx);
- ctx = NULL;
- }
- GNUNET_CURL_gnunet_rc_destroy (rc);
-}
+#include "test_bank_interpreter.h"
/**
@@ -407,33 +36,23 @@ do_shutdown (void *cls)
static void
run (void *cls)
{
- struct InterpreterState *is;
- static struct Command commands[] =
+ int *resultp = cls;
+ static struct TBI_Command commands[] =
{
/* Add EUR:5.01 to account 42 */
- { .oc = OC_ADMIN_ADD_INCOMING,
+ { .oc = TBI_OC_ADMIN_ADD_INCOMING,
.label = "deposit-1",
.expected_response_code = MHD_HTTP_OK,
.details.admin_add_incoming.credit_account_no = 1,
.details.admin_add_incoming.debit_account_no = 2,
.details.admin_add_incoming.amount = "PUDOS:5.01" },
- { .oc = OC_END }
+ { .oc = TBI_OC_END }
};
- is = GNUNET_new (struct InterpreterState);
- is->commands = commands;
- ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
- &rc);
- rc = GNUNET_CURL_gnunet_rc_create (ctx);
- GNUNET_assert (NULL != ctx);
- is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
- is);
- timeout_task
- = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
- (GNUNET_TIME_UNIT_SECONDS, 150),
- &do_timeout, is);
- GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
+ TBI_run_interpreter (resultp,
+ 0 /* we use the "real" taler bank */,
+ commands);
}
@@ -449,6 +68,7 @@ main (int argc,
{
struct GNUNET_OS_Process *bankd;
unsigned int cnt;
+ int result;
GNUNET_log_setup ("test-bank-api",
"WARNING",
@@ -483,7 +103,7 @@ main (int argc,
fprintf (stderr, "\n");
result = GNUNET_SYSERR;
if (cnt <= 30)
- GNUNET_SCHEDULER_run (&run, NULL);
+ GNUNET_SCHEDULER_run (&run, &result);
GNUNET_OS_process_kill (bankd,
SIGTERM);
GNUNET_OS_process_wait (bankd);
diff --git a/src/bank-lib/test_bank_interpreter.c b/src/bank-lib/test_bank_interpreter.c
new file mode 100644
index 000000000..8a57c4b62
--- /dev/null
+++ b/src/bank-lib/test_bank_interpreter.c
@@ -0,0 +1,349 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2016 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file bank/test_bank_interpreter.c
+ * @brief interpreter for tests of the bank's HTTP API interface
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "taler_util.h"
+#include "taler_signatures.h"
+#include "taler_bank_service.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include <microhttpd.h>
+#include "test_bank_interpreter.h"
+
+
+
+/**
+ * State of the interpreter loop.
+ */
+struct InterpreterState
+{
+ /**
+ * Keys from the bank.
+ */
+ const struct TALER_BANK_Keys *keys;
+
+ /**
+ * Commands the interpreter will run.
+ */
+ struct TBI_Command *commands;
+
+ /**
+ * Interpreter task (if one is scheduled).
+ */
+ struct GNUNET_SCHEDULER_Task *task;
+
+ /**
+ * Main execution context for the main loop.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Task run on timeout.
+ */
+ struct GNUNET_SCHEDULER_Task *timeout_task;
+
+ /**
+ * Context for running the main loop with GNUnet's SCHEDULER API.
+ */
+ struct GNUNET_CURL_RescheduleContext *rc;
+
+ /**
+ * Where to store the final result.
+ */
+ int *resultp;
+
+ /**
+ * Instruction pointer. Tells #interpreter_run() which
+ * instruction to run next.
+ */
+ unsigned int ip;
+
+};
+
+
+/**
+ * The testcase failed, return with an error code.
+ *
+ * @param is interpreter state to clean up
+ */
+static void
+fail (struct InterpreterState *is)
+{
+ *is->resultp = GNUNET_SYSERR;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+#if 0
+/**
+ * Find a command by label.
+ *
+ * @param is interpreter state to search
+ * @param label label to look for
+ * @return NULL if command was not found
+ */
+static const struct TBI_Command *
+find_command (const struct InterpreterState *is,
+ const char *label)
+{
+ unsigned int i;
+ const struct TBI_Command *cmd;
+
+ if (NULL == label)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Attempt to lookup command for empty label\n");
+ return NULL;
+ }
+ for (i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++)
+ if ( (NULL != cmd->label) &&
+ (0 == strcmp (cmd->label,
+ label)) )
+ return cmd;
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command not found: %s\n",
+ label);
+ return NULL;
+}
+#endif
+
+
+/**
+ * Run the main interpreter loop that performs bank operations.
+ *
+ * @param cls contains the `struct InterpreterState`
+ */
+static void
+interpreter_run (void *cls);
+
+
+/**
+ * Function called upon completion of our /admin/add/incoming request.
+ *
+ * @param cls closure with the interpreter state
+ * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
+ * 0 if the bank's reply is bogus (fails to follow the protocol)
+ * @param json detailed response from the HTTPD, or NULL if reply was not in JSON
+ */
+static void
+add_incoming_cb (void *cls,
+ unsigned int http_status,
+ const json_t *json)
+{
+ struct InterpreterState *is = cls;
+ struct TBI_Command *cmd = &is->commands[is->ip];
+
+ cmd->details.admin_add_incoming.aih = NULL;
+ if (cmd->expected_response_code != http_status)
+ {
+ GNUNET_break (0);
+ if (NULL != json)
+ {
+ fprintf (stderr,
+ "Unexpected response code %u:\n",
+ http_status);
+ json_dumpf (json, stderr, 0);
+ fprintf (stderr, "\n");
+ }
+ fail (is);
+ return;
+ }
+ is->ip++;
+ is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
+ is);
+}
+
+
+/**
+ * Run the main interpreter loop that performs bank operations.
+ *
+ * @param cls contains the `struct InterpreterState`
+ */
+static void
+interpreter_run (void *cls)
+{
+ struct InterpreterState *is = cls;
+ struct TBI_Command *cmd = &is->commands[is->ip];
+ struct TALER_Amount amount;
+ const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+ is->task = NULL;
+ tc = GNUNET_SCHEDULER_get_task_context ();
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ {
+ fprintf (stderr,
+ "Test aborted by shutdown request\n");
+ fail (is);
+ return;
+ }
+ switch (cmd->oc)
+ {
+ case TBI_OC_END:
+ *is->resultp = GNUNET_OK;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ case TBI_OC_ADMIN_ADD_INCOMING:
+
+ if (GNUNET_OK !=
+ TALER_string_to_amount (cmd->details.admin_add_incoming.amount,
+ &amount))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to parse amount `%s' at %u\n",
+ cmd->details.admin_add_incoming.amount,
+ is->ip);
+ fail (is);
+ return;
+ }
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+ &cmd->details.admin_add_incoming.wtid,
+ sizeof (cmd->details.admin_add_incoming.wtid));
+ cmd->details.admin_add_incoming.aih
+ = TALER_BANK_admin_add_incoming (is->ctx,
+ "http://localhost:8081",
+ &cmd->details.admin_add_incoming.wtid,
+ &amount,
+ cmd->details.admin_add_incoming.debit_account_no,
+ cmd->details.admin_add_incoming.credit_account_no,
+ &add_incoming_cb,
+ is);
+ if (NULL == cmd->details.admin_add_incoming.aih)
+ {
+ GNUNET_break (0);
+ fail (is);
+ return;
+ }
+ return;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unknown instruction %d at %u (%s)\n",
+ cmd->oc,
+ is->ip,
+ cmd->label);
+ fail (is);
+ return;
+ }
+}
+
+
+/**
+ * Function run on timeout.
+ *
+ * @param cls the `struct InterpreterState`
+ */
+static void
+do_timeout (void *cls)
+{
+ struct InterpreterState *is = cls;
+
+ is->timeout_task = NULL;
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * Function run when the test terminates (good or bad).
+ * Cleans up our state.
+ *
+ * @param cls the interpreter state.
+ */
+static void
+do_shutdown (void *cls)
+{
+ struct InterpreterState *is = cls;
+ struct TBI_Command *cmd;
+ unsigned int i;
+
+ if (NULL != is->timeout_task)
+ {
+ GNUNET_SCHEDULER_cancel (is->timeout_task);
+ is->timeout_task = NULL;
+ }
+
+ for (i=0;TBI_OC_END != (cmd = &is->commands[i])->oc;i++)
+ {
+ switch (cmd->oc)
+ {
+ case TBI_OC_END:
+ GNUNET_assert (0);
+ break;
+ case TBI_OC_ADMIN_ADD_INCOMING:
+ if (NULL != cmd->details.admin_add_incoming.aih)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command %u (%s) did not complete\n",
+ i,
+ cmd->label);
+ TALER_BANK_admin_add_incoming_cancel (cmd->details.admin_add_incoming.aih);
+ cmd->details.admin_add_incoming.aih = NULL;
+ }
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unknown instruction %d at %u (%s)\n",
+ cmd->oc,
+ i,
+ cmd->label);
+ break;
+ }
+ }
+ if (NULL != is->task)
+ {
+ GNUNET_SCHEDULER_cancel (is->task);
+ is->task = NULL;
+ }
+ GNUNET_CURL_fini (is->ctx);
+ is->ctx = NULL;
+ GNUNET_CURL_gnunet_rc_destroy (is->rc);
+ GNUNET_free (is);
+}
+
+
+/**
+ * Entry point to the interpeter.
+ *
+ * @param resultp where to store the final result
+ * @param bank_port on which port to launch the bank, 0 for none
+ * @param commands list of commands to run
+ */
+void
+TBI_run_interpreter (int *resultp,
+ uint16_t bank_port,
+ struct TBI_Command *commands)
+{
+ struct InterpreterState *is;
+
+ is = GNUNET_new (struct InterpreterState);
+ is->resultp = resultp;
+ is->commands = commands;
+ is->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &is->rc);
+ GNUNET_assert (NULL != is->ctx);
+ is->rc = GNUNET_CURL_gnunet_rc_create (is->ctx);
+ is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
+ is);
+ is->timeout_task
+ = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+ (GNUNET_TIME_UNIT_SECONDS, 150),
+ &do_timeout, is);
+ GNUNET_SCHEDULER_add_shutdown (&do_shutdown, is);
+}
+
+/* end of test_bank_interpeter.c */
diff --git a/src/bank-lib/test_bank_interpreter.h b/src/bank-lib/test_bank_interpreter.h
new file mode 100644
index 000000000..35873840a
--- /dev/null
+++ b/src/bank-lib/test_bank_interpreter.h
@@ -0,0 +1,127 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2016 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file bank/test_bank_interpreter.h
+ * @brief interpreter for tests of the bank's HTTP API interface
+ * @author Christian Grothoff
+ */
+#ifndef TEST_BANK_INTERPRETER_H
+#define TEST_BANK_INTERPRETER_H
+
+#include "taler_util.h"
+#include "taler_signatures.h"
+#include "taler_bank_service.h"
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include <microhttpd.h>
+
+
+/**
+ * Opcodes for the interpreter.
+ */
+enum TBI_OpCode
+{
+ /**
+ * Termination code, stops the interpreter loop (with success).
+ */
+ TBI_OC_END = 0,
+
+ /**
+ * Add funds to a reserve by (faking) incoming wire transfer.
+ */
+ TBI_OC_ADMIN_ADD_INCOMING
+
+};
+
+
+/**
+ * Details for a bank operation to execute.
+ */
+struct TBI_Command
+{
+ /**
+ * Opcode of the command.
+ */
+ enum TBI_OpCode oc;
+
+ /**
+ * Label for the command, can be NULL.
+ */
+ const char *label;
+
+ /**
+ * Which response code do we expect for this command?
+ */
+ unsigned int expected_response_code;
+
+ /**
+ * Details about the command.
+ */
+ union
+ {
+
+ /**
+ * Information for a #TBI_OC_ADMIN_ADD_INCOMING command.
+ */
+ struct
+ {
+
+ /**
+ * String describing the amount to add to the reserve.
+ */
+ const char *amount;
+
+ /**
+ * Credited account number.
+ */
+ uint64_t credit_account_no;
+
+ /**
+ * Debited account number.
+ */
+ uint64_t debit_account_no;
+
+ /**
+ * Wire transfer identifier to use. Initialized to
+ * a random value.
+ */
+ struct TALER_WireTransferIdentifierRawP wtid;
+
+ /**
+ * Set to the API's handle during the operation.
+ */
+ struct TALER_BANK_AdminAddIncomingHandle *aih;
+
+ } admin_add_incoming;
+
+ } details;
+
+};
+
+
+/**
+ * Entry point to the interpeter.
+ *
+ * @param resultp where to store the final result
+ * @param bank_port on which port to launch the bank, 0 for none
+ * @param commands list of commands to run
+ */
+void
+TBI_run_interpreter (int *resultp,
+ uint16_t bank_port,
+ struct TBI_Command *commands);
+
+#endif