move rewind command to exchange, add proper support for rewinding in batches, modify API to rewind to label

This commit is contained in:
Christian Grothoff 2020-07-03 20:57:01 +02:00
parent 2279c8ab17
commit 49f466df40
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
6 changed files with 283 additions and 12 deletions

View File

@ -388,10 +388,9 @@ struct TALER_TESTING_Interpreter
void *final_cleanup_cb_cls; void *final_cleanup_cb_cls;
/** /**
* Instruction pointer. Tells #interpreter_run() which * Instruction pointer. Tells #interpreter_run() which instruction to run
* instruction to run next. Need (signed) int because * next. Need (signed) int because it gets -1 when rewinding the
* it gets -1 when rewinding the interpreter to the first * interpreter to the first CMD.
* CMD.
*/ */
int ip; int ip;
@ -599,7 +598,22 @@ TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is);
* @return a end-command. * @return a end-command.
*/ */
struct TALER_TESTING_Command struct TALER_TESTING_Command
TALER_TESTING_cmd_end (); TALER_TESTING_cmd_end (void);
/**
* Make the instruction pointer point to @a target_label
* only if @a counter is greater than zero.
*
* @param label command label
* @param target_label label of the new instruction pointer's destination after the jump;
* must be before the current instruction
* @param counter counts how many times the rewinding is to happen.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_rewind_ip (const char *label,
const char *target_label,
unsigned int counter);
/** /**
@ -816,7 +830,6 @@ TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb,
* @param config_filename configuration filename. * @param config_filename configuration filename.
* @param bank_url base URL of the bank, used by `wget' to check * @param bank_url base URL of the bank, used by `wget' to check
* that the bank was started right. * that the bank was started right.
*
* @return the process, or NULL if the process could not * @return the process, or NULL if the process could not
* be started. * be started.
*/ */
@ -839,6 +852,7 @@ TALER_TESTING_run_bank (const char *config_filename,
struct TALER_TESTING_LibeufinServices struct TALER_TESTING_LibeufinServices
TALER_TESTING_run_libeufin (const struct TALER_TESTING_BankConfiguration *bc); TALER_TESTING_run_libeufin (const struct TALER_TESTING_BankConfiguration *bc);
/** /**
* Runs the Fakebank by guessing / extracting the portnumber * Runs the Fakebank by guessing / extracting the portnumber
* from the base URL. * from the base URL.
@ -1896,6 +1910,18 @@ TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is);
struct TALER_TESTING_Command * struct TALER_TESTING_Command *
TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd); TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd);
/**
* Set what command the batch should be at.
*
* @param cmd current batch command
* @param new_ip where to move the IP
*/
void
TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
unsigned int new_ip);
/** /**
* Make a serialize-keys CMD. * Make a serialize-keys CMD.
* *

View File

@ -61,6 +61,7 @@ libtalertesting_la_SOURCES = \
testing_api_cmd_refund.c \ testing_api_cmd_refund.c \
testing_api_cmd_refresh.c \ testing_api_cmd_refresh.c \
testing_api_cmd_revoke.c \ testing_api_cmd_revoke.c \
testing_api_cmd_rewind.c \
testing_api_cmd_serialize_keys.c \ testing_api_cmd_serialize_keys.c \
testing_api_cmd_signal.c \ testing_api_cmd_signal.c \
testing_api_cmd_sleep.c \ testing_api_cmd_sleep.c \

View File

@ -228,5 +228,27 @@ TALER_TESTING_cmd_batch_get_current (const struct TALER_TESTING_Command *cmd)
{ {
struct BatchState *bs = cmd->cls; struct BatchState *bs = cmd->cls;
GNUNET_assert (cmd->run == &batch_run);
return &bs->batch[bs->batch_ip]; return &bs->batch[bs->batch_ip];
} }
/**
* Set what command the batch should be at.
*
* @param cmd current batch command
* @param new_ip where to move the IP
*/
void
TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd,
unsigned int new_ip)
{
struct BatchState *bs = cmd->cls;
/* sanity checks */
GNUNET_assert (cmd->run == &batch_run);
for (unsigned int i = 0; i < new_ip; i++)
GNUNET_assert (NULL != bs->batch[i].label);
/* actual logic */
bs->batch_ip = new_ip;
}

View File

@ -0,0 +1,222 @@
/*
This file is part of TALER
Copyright (C) 2014-2020 Taler Systems SA
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, see
<http://www.gnu.org/licenses/>
*/
/**
* @file testing/testing_api_cmd_rewind.c
* @brief command to rewind the instruction pointer.
* @author Marcello Stanisci
* @author Christian Grothoff
*/
#include "platform.h"
#include <taler/taler_exchange_service.h>
#include <taler/taler_testing_lib.h>
#include "taler_testing_lib.h"
/**
* State for a "rewind" CMD.
*/
struct RewindIpState
{
/**
* Instruction pointer to set into the interpreter.
*/
const char *target_label;
/**
* How many times this set should take place. However, this value lives at
* the calling process, and this CMD is only in charge of checking and
* decremeting it.
*/
unsigned int counter;
};
/**
* Only defined to respect the API.
*/
static void
rewind_ip_cleanup (void *cls,
const struct TALER_TESTING_Command *cmd)
{
(void) cls;
(void) cmd;
}
/**
* Seek for the @a target command in @a batch (and rewind to it
* if successful).
*
* @param is the interpreter state (for failures)
* @param cmd batch to search for @a target
* @param target command to search for
* @return #GNUNET_OK on success, #GNUNET_NO if target was not found,
* #GNUNET_SYSERR if target is in the future and we failed
*/
static int
seek_batch (struct TALER_TESTING_Interpreter *is,
const struct TALER_TESTING_Command *cmd,
const struct TALER_TESTING_Command *target)
{
unsigned int new_ip;
#define BATCH_INDEX 1
struct TALER_TESTING_Command *batch;
struct TALER_TESTING_Command *current;
struct TALER_TESTING_Command *icmd;
const struct TALER_TESTING_Command *match;
current = TALER_TESTING_cmd_batch_get_current (cmd);
GNUNET_assert (GNUNET_OK ==
TALER_TESTING_get_trait_cmd (cmd,
BATCH_INDEX,
&batch));
match = NULL;
for (new_ip = 0;
NULL != (icmd = &batch[new_ip]);
new_ip++)
{
if (current == target)
current = NULL;
if (icmd == target)
{
match = icmd;
break;
}
if (TALER_TESTING_cmd_is_batch (icmd))
{
int ret = seek_batch (is,
icmd,
target);
if (GNUNET_SYSERR == ret)
return GNUNET_SYSERR; /* failure! */
if (GNUNET_OK == ret)
{
match = icmd;
break;
}
}
}
if (NULL == current)
{
/* refuse to jump forward */
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return GNUNET_SYSERR;
}
if (NULL == match)
return GNUNET_NO; /* not found */
TALER_TESTING_cmd_batch_set_current (cmd,
new_ip);
return GNUNET_OK;
}
/**
* Run the "rewind" CMD.
*
* @param cls closure.
* @param cmd command being executed now.
* @param is the interpreter state.
*/
static void
rewind_ip_run (void *cls,
const struct TALER_TESTING_Command *cmd,
struct TALER_TESTING_Interpreter *is)
{
struct RewindIpState *ris = cls;
const struct TALER_TESTING_Command *target;
unsigned int new_ip;
(void) cmd;
if (0 == ris->counter)
{
TALER_TESTING_interpreter_next (is);
return;
}
target
= TALER_TESTING_interpreter_lookup_command (is,
ris->target_label);
if (NULL == target)
{
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
ris->counter--;
for (new_ip = 0;
NULL != is->commands[new_ip].label;
new_ip++)
{
const struct TALER_TESTING_Command *cmd = &is->commands[new_ip];
if (cmd == target)
break;
if (TALER_TESTING_cmd_is_batch (cmd))
{
int ret = seek_batch (is,
cmd,
target);
if (GNUNET_SYSERR == ret)
return; /* failure! */
if (GNUNET_OK == ret)
break;
}
}
if (new_ip > is->ip)
{
/* refuse to jump forward */
GNUNET_break (0);
TALER_TESTING_interpreter_fail (is);
return;
}
is->ip = new_ip - 1; /* -1 because the next function will advance by one */
TALER_TESTING_interpreter_next (is);
}
/**
* Make the instruction pointer point to @a new_ip
* only if @a counter is greater than zero.
*
* @param label command label
* @param target_label label of the new instruction pointer's destination after the jump;
* must be before the current instruction
* @param counter counts how many times the rewinding is to happen.
*/
struct TALER_TESTING_Command
TALER_TESTING_cmd_rewind_ip (const char *label,
const char *target_label,
unsigned int counter)
{
struct RewindIpState *ris;
ris = GNUNET_new (struct RewindIpState);
ris->target_label = target_label;
ris->counter = counter;
{
struct TALER_TESTING_Command cmd = {
.cls = ris,
.label = label,
.run = &rewind_ip_run,
.cleanup = &rewind_ip_cleanup
};
return cmd;
}
}

View File

@ -40,7 +40,6 @@ stat_cleanup (void *cls,
(void) cls; (void) cls;
(void) cmd; (void) cmd;
/* nothing to clean. */ /* nothing to clean. */
return;
} }

View File

@ -69,6 +69,7 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is,
#define BATCH_INDEX 1 #define BATCH_INDEX 1
struct TALER_TESTING_Command *batch; struct TALER_TESTING_Command *batch;
struct TALER_TESTING_Command *current; struct TALER_TESTING_Command *current;
struct TALER_TESTING_Command *icmd;
const struct TALER_TESTING_Command *match; const struct TALER_TESTING_Command *match;
current = TALER_TESTING_cmd_batch_get_current (cmd); current = TALER_TESTING_cmd_batch_get_current (cmd);
@ -79,15 +80,15 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is,
/* We must do the loop forward, but we can find the last match */ /* We must do the loop forward, but we can find the last match */
match = NULL; match = NULL;
for (unsigned int j = 0; for (unsigned int j = 0;
NULL != (cmd = &batch[j])->label; NULL != (icmd = &batch[j])->label;
j++) j++)
{ {
if (current == cmd) if (current == icmd)
break; /* do not go past current command */ break; /* do not go past current command */
if ( (NULL != cmd->label) && if ( (NULL != icmd->label) &&
(0 == strcmp (cmd->label, (0 == strcmp (icmd->label,
label)) ) label)) )
match = cmd; match = icmd;
} }
if (NULL != match) if (NULL != match)
return match; return match;