GNUnet  0.11.x
Data Structures | Macros | Functions
testing_api_loop.c File Reference

main interpreter loop for testcases More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_testing_ng_lib.h"
#include "testing.h"
Include dependency graph for testing_api_loop.c:

Go to the source code of this file.

Data Structures

struct  GNUNET_TESTING_Interpreter
 Global state of the interpreter, used by a command to access information about other commands. More...
 
struct  MainParams
 Closure for loop_run(). More...
 

Macros

#define BATCH_INDEX   1
 

Functions

const struct GNUNET_TESTING_CommandGNUNET_TESTING_interpreter_lookup_command (struct GNUNET_TESTING_Interpreter *is, const char *label)
 Lookup command by label. More...
 
static void finish_test (void *cls)
 Finish the test run, return the final result. More...
 
static void interpreter_run (void *cls)
 Run the main interpreter loop that performs exchange operations. More...
 
static void interpreter_next (void *cls)
 Current command is done, run the next one. More...
 
void GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
 Current command failed, clean up and fail the test case. More...
 
const char * GNUNET_TESTING_interpreter_get_current_label (struct GNUNET_TESTING_Interpreter *is)
 Obtain label of the command being now run. More...
 
static void do_timeout (void *cls)
 Function run when the test terminates (good or bad) with timeout. More...
 
void GNUNET_TESTING_run (struct GNUNET_TESTING_Command *commands, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_ResultCallback rc, void *rc_cls)
 Run the testsuite. More...
 
static void handle_result (void *cls, enum GNUNET_GenericReturnValue rv)
 Function called with the final result of the test. More...
 
static void loop_run (void *cls)
 Main function to run the test cases. More...
 
int GNUNET_TESTING_main (struct GNUNET_TESTING_Command *commands, struct GNUNET_TIME_Relative timeout)
 Start a GNUnet scheduler event loop and run the testsuite. More...
 
void GNUNET_TESTING_async_fail (struct GNUNET_TESTING_AsyncContext *ac)
 The asynchronous command of ac has failed. More...
 
void GNUNET_TESTING_async_finish (struct GNUNET_TESTING_AsyncContext *ac)
 The asynchronous command of ac has finished. More...
 

Detailed Description

main interpreter loop for testcases

Author
Christian Grothoff (GNU Taler testing)
Marcello Stanisci (GNU Taler testing)
t3sserakt

Definition in file testing_api_loop.c.

Macro Definition Documentation

◆ BATCH_INDEX

#define BATCH_INDEX   1

Function Documentation

◆ GNUNET_TESTING_interpreter_lookup_command()

const struct GNUNET_TESTING_Command* GNUNET_TESTING_interpreter_lookup_command ( struct GNUNET_TESTING_Interpreter is,
const char *  label 
)

Lookup command by label.

Parameters
isinterpreter to lookup command in
labellabel of the command to lookup.
Returns
the command, if it is found, or NULL.

Definition at line 86 of file testing_api_loop.c.

89 {
90  if (NULL == label)
91  {
93  "Attempt to lookup command for empty label\n");
94  return NULL;
95  }
96  /* Search backwards as we most likely reference recent commands */
97  for (int i = is->ip; i >= 0; i--)
98  {
99  const struct GNUNET_TESTING_Command *cmd = &is->commands[i];
100 
101  /* Give precedence to top-level commands. */
102  if ( (NULL != cmd->label) &&
103  (0 == strcmp (cmd->label,
104  label)) )
105  return cmd;
106 
108  {
109 #define BATCH_INDEX 1
110  struct GNUNET_TESTING_Command *batch;
111  struct GNUNET_TESTING_Command *current;
112  struct GNUNET_TESTING_Command *icmd;
113  const struct GNUNET_TESTING_Command *match;
114 
118  BATCH_INDEX,
119  &batch));
120  /* We must do the loop forward, but we can find the last match */
121  match = NULL;
122  for (unsigned int j = 0;
123  NULL != (icmd = &batch[j])->label;
124  j++)
125  {
126  if (current == icmd)
127  break; /* do not go past current command */
128  if ( (NULL != icmd->label) &&
129  (0 == strcmp (icmd->label,
130  label)) )
131  match = icmd;
132  }
133  if (NULL != match)
134  return match;
135  }
136  }
138  "Command `%s' not found\n",
139  label);
140  return NULL;
141 }
static struct GNUNET_NT_InterfaceScanner * is
Network scanner to determine network types.
#define GNUNET_log(kind,...)
@ GNUNET_OK
Definition: gnunet_common.h:95
enum GNUNET_GenericReturnValue GNUNET_TESTING_get_trait_cmd(const struct GNUNET_TESTING_Command *cmd, unsigned int index, struct GNUNET_TESTING_Command **_cmd)
Obtain a command from cmd.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
A command to be run by the interpreter.
const char * label
Label for the command.
struct GNUNET_TESTING_Command * GNUNET_TESTING_cmd_batch_get_current_(const struct GNUNET_TESTING_Command *cmd)
Obtain what command the batch is at.
bool GNUNET_TESTING_cmd_is_batch_(const struct GNUNET_TESTING_Command *cmd)
Test if this command is a batch command.
#define BATCH_INDEX

References BATCH_INDEX, GNUNET_assert, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_OK, GNUNET_TESTING_cmd_batch_get_current_(), GNUNET_TESTING_cmd_is_batch_(), GNUNET_TESTING_get_trait_cmd(), is, and GNUNET_TESTING_Command::label.

Referenced by connect_peers_run(), hello_world_run(), run_finish(), send_simple_run(), start_peer_run(), stop_peer_run(), stop_testing_system_run(), and system_destroy_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ finish_test()

static void finish_test ( void *  cls)
static

Finish the test run, return the final result.

Parameters
clsthe struct GNUNET_TESTING_Interpreter

Definition at line 150 of file testing_api_loop.c.

151 {
152  struct GNUNET_TESTING_Interpreter *is = cls;
153  struct GNUNET_TESTING_Command *cmd;
154  const char *label;
155 
156  is->final_task = NULL;
157  label = is->commands[is->ip].label;
158  if (NULL == label)
159  label = "END";
161  "Interpreter finishes at `%s' with status %d\n",
162  label,
163  is->result);
164  for (unsigned int j = 0;
165  NULL != (cmd = &is->commands[j])->label;
166  j++)
167  {
169  "Cleaning up cmd %s\n",
170  cmd->label);
171  cmd->cleanup (cmd->cls);
173  "Cleaned up cmd %s\n",
174  cmd->label);
175  }
176  if (NULL != is->task)
177  {
178  GNUNET_SCHEDULER_cancel (is->task);
179  is->task = NULL;
180  }
181  if (NULL != is->timeout_task)
182  {
183  GNUNET_SCHEDULER_cancel (is->timeout_task);
184  is->timeout_task = NULL;
185  }
186  GNUNET_free (is->commands);
187  is->rc (is->rc_cls,
188  is->result);
189  GNUNET_free (is);
190 }
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
void(* cleanup)(void *cls)
Clean up after the command.
void * cls
Closure for all commands with command-specific context information.
Global state of the interpreter, used by a command to access information about other commands.

References GNUNET_TESTING_Command::cleanup, GNUNET_TESTING_Command::cls, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_SCHEDULER_cancel(), is, and GNUNET_TESTING_Command::label.

Referenced by do_timeout(), GNUNET_TESTING_interpreter_fail(), and interpreter_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ interpreter_run()

static void interpreter_run ( void *  cls)
static

Run the main interpreter loop that performs exchange operations.

Run the main interpreter loop.

Parameters
clscontains the struct InterpreterState
clscontains the struct GNUNET_TESTING_Interpreter

Definition at line 286 of file testing_api_loop.c.

287 {
288  struct GNUNET_TESTING_Interpreter *is = cls;
289  struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
290 
291  is->task = NULL;
292  if (NULL == cmd->label)
293  {
295  "Running command END\n");
296  is->result = GNUNET_OK;
297  finish_test (is);
298  return;
299  }
301  "Running command `%s'\n",
302  cmd->label);
303  cmd->start_time
304  = cmd->last_req_time
306  cmd->num_tries = 1;
307  if (NULL != cmd->ac)
308  {
309  cmd->ac->is = is;
310  cmd->ac->cont = &interpreter_next;
311  cmd->ac->cont_cls = is;
312  cmd->ac->finished = GNUNET_NO;
313  }
314  cmd->run (cmd->cls,
315  is);
316  if (NULL == cmd->ac)
317  {
319  }
320  else if ( (cmd->asynchronous_finish) &&
321  (NULL != cmd->ac->cont) )
322  {
323  cmd->ac->cont = NULL;
325  }
326 }
@ GNUNET_NO
Definition: gnunet_common.h:94
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:86
GNUNET_SCHEDULER_TaskCallback cont
Function to call when done.
void * cont_cls
Closure for cont.
struct GNUNET_TESTING_Interpreter * is
Interpreter we are part of.
enum GNUNET_GenericReturnValue finished
Indication if the command finished (GNUNET_OK).
struct GNUNET_TIME_Absolute last_req_time
When did we start the last run of this command? Delta to finish_time gives the latency for the last s...
struct GNUNET_TESTING_AsyncContext * ac
Pointer to the asynchronous context in the command's closure.
void(* run)(void *cls, struct GNUNET_TESTING_Interpreter *is)
Runs the command.
bool asynchronous_finish
If "true", the interpreter should not immediately call finish, even if finish is non-NULL.
unsigned int num_tries
How often did we try to execute this command? (In case it is a request that is repated....
struct GNUNET_TIME_Absolute start_time
When did the execution of this command start?
static void interpreter_next(void *cls)
Current command is done, run the next one.
static void finish_test(void *cls)
Finish the test run, return the final result.

References GNUNET_TESTING_Command::ac, GNUNET_TESTING_Command::asynchronous_finish, GNUNET_TESTING_Command::cls, GNUNET_TESTING_AsyncContext::cont, GNUNET_TESTING_AsyncContext::cont_cls, finish_test(), GNUNET_TESTING_AsyncContext::finished, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_NO, GNUNET_OK, GNUNET_TIME_absolute_get(), interpreter_next(), GNUNET_TESTING_AsyncContext::is, is, GNUNET_TESTING_Command::label, GNUNET_TESTING_Command::last_req_time, GNUNET_TESTING_Command::num_tries, GNUNET_TESTING_Command::run, and GNUNET_TESTING_Command::start_time.

Referenced by GNUNET_TESTING_run(), and interpreter_next().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ interpreter_next()

static void interpreter_next ( void *  cls)
static

Current command is done, run the next one.

Definition at line 206 of file testing_api_loop.c.

207 {
208  struct GNUNET_TESTING_Interpreter *is = cls;
209  static unsigned long long ipc;
210  static struct GNUNET_TIME_Absolute last_report;
211  struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
212 
213  if (GNUNET_SYSERR == is->result)
214  return; /* ignore, we already failed! */
216  if ( (! GNUNET_TESTING_cmd_is_batch_ (cmd)) ||
218  is->ip++;
219  if (0 == (ipc % 1000))
220  {
221  if (0 != ipc)
223  "Interpreter executed 1000 instructions in %s\n",
225  GNUNET_TIME_absolute_get_duration (last_report),
226  GNUNET_YES));
227  last_report = GNUNET_TIME_absolute_get ();
228  }
229  ipc++;
231  is);
232 }
@ GNUNET_YES
Definition: gnunet_common.h:97
@ GNUNET_SYSERR
Definition: gnunet_common.h:93
@ GNUNET_ERROR_TYPE_MESSAGE
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1296
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:263
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:557
struct GNUNET_TIME_Absolute finish_time
When did the execution of this command finish?
Time for absolute times used by GNUnet, in microseconds.
bool GNUNET_TESTING_cmd_batch_next_(void *cls)
Advance internal pointer to next command.
static void interpreter_run(void *cls)
Run the main interpreter loop that performs exchange operations.

References GNUNET_TESTING_Command::cls, GNUNET_TESTING_Command::finish_time, GNUNET_ERROR_TYPE_MESSAGE, GNUNET_log, GNUNET_SCHEDULER_add_now(), GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TESTING_cmd_batch_next_(), GNUNET_TESTING_cmd_is_batch_(), GNUNET_TIME_absolute_get(), GNUNET_TIME_absolute_get_duration(), GNUNET_YES, interpreter_run(), and is.

Referenced by interpreter_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_TESTING_interpreter_fail()

void GNUNET_TESTING_interpreter_fail ( struct GNUNET_TESTING_Interpreter is)

Current command failed, clean up and fail the test case.

Parameters
isinterpreter state.

Definition at line 236 of file testing_api_loop.c.

237 {
238  struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
239 
240  if (GNUNET_SYSERR == is->result)
241  {
242  GNUNET_break (0);
243  return; /* ignore, we already failed! */
244  }
245  if (NULL != cmd)
246  {
248  "Failed at command `%s'\n",
249  cmd->label);
250  while (GNUNET_TESTING_cmd_is_batch_ (cmd))
251  {
254  "Failed in batch at command `%s'\n",
255  cmd->label);
256  }
257  }
258  else
259  {
261  "Failed with CMD being NULL!\n");
262  }
263  is->result = GNUNET_SYSERR;
264  GNUNET_assert (NULL == is->final_task);
265  is->final_task = GNUNET_SCHEDULER_add_now (&finish_test,
266  is);
267 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.

References finish_test(), GNUNET_assert, GNUNET_break, GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_SCHEDULER_add_now(), GNUNET_SYSERR, GNUNET_TESTING_cmd_batch_get_current_(), GNUNET_TESTING_cmd_is_batch_(), is, and GNUNET_TESTING_Command::label.

Referenced by exp_cb(), GNUNET_TESTING_async_fail(), netjail_stop_run(), run_finish(), start_helper(), and start_peer_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_TESTING_interpreter_get_current_label()

const char* GNUNET_TESTING_interpreter_get_current_label ( struct GNUNET_TESTING_Interpreter is)

Obtain label of the command being now run.

Parameters
isinterpreter state.
Returns
the label.

Definition at line 271 of file testing_api_loop.c.

273 {
274  struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
275 
276  return cmd->label;
277 }

References is, and GNUNET_TESTING_Command::label.

◆ do_timeout()

static void do_timeout ( void *  cls)
static

Function run when the test terminates (good or bad) with timeout.

Parameters
clsthe interpreter state

Definition at line 335 of file testing_api_loop.c.

336 {
337  struct GNUNET_TESTING_Interpreter *is = cls;
338 
339  is->timeout_task = NULL;
341  "Terminating test due to global timeout\n");
342  is->result = GNUNET_SYSERR;
343  finish_test (is);
344 }

References finish_test(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_SYSERR, and is.

Referenced by GNUNET_TESTING_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_TESTING_run()

void GNUNET_TESTING_run ( struct GNUNET_TESTING_Command commands,
struct GNUNET_TIME_Relative  timeout,
GNUNET_TESTING_ResultCallback  rc,
void *  rc_cls 
)

Run the testsuite.

Note, CMDs are copied into the interpreter state because they are usually defined into the "run" method that returns after having scheduled the test interpreter.

Parameters
commandsthe list of command to execute
timeouthow long to wait for each command to execute
rcfunction to call with the final result
rc_clsclosure for rc

Definition at line 348 of file testing_api_loop.c.

352 {
354  unsigned int i;
355 
357  is->rc = rc;
358  is->rc_cls = rc_cls;
359  /* get the number of commands */
360  for (i = 0; NULL != commands[i].label; i++)
361  ;
362  is->commands = GNUNET_new_array (i + 1,
363  struct GNUNET_TESTING_Command);
364  memcpy (is->commands,
365  commands,
366  sizeof (struct GNUNET_TESTING_Command) * i);
367  is->timeout_task
369  &do_timeout,
370  is);
372  is);
373 }
static struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gnunet-abd.c:61
static struct VoipCommand commands[]
List of supported commands.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
GNUNET_TESTING_ResultCallback rc
Function to call with the test result.
void * rc_cls
Closure for rc.
static void do_timeout(void *cls)
Function run when the test terminates (good or bad) with timeout.

References commands, do_timeout(), GNUNET_new, GNUNET_new_array, GNUNET_SCHEDULER_add_delayed(), GNUNET_SCHEDULER_add_now(), interpreter_run(), is, GNUNET_TESTING_Interpreter::rc, GNUNET_TESTING_Interpreter::rc_cls, and timeout.

Referenced by loop_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ handle_result()

static void handle_result ( void *  cls,
enum GNUNET_GenericReturnValue  rv 
)
static

Function called with the final result of the test.

Parameters
clsthe struct MainParams
rvGNUNET_OK if the test passed

Definition at line 406 of file testing_api_loop.c.

408 {
409  struct MainParams *mp = cls;
410 
412  "Test exits with status %d\n",
413  rv);
414  if (GNUNET_OK != rv)
415  mp->rv = EXIT_FAILURE;
417 }
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:531
Closure for loop_run().
int rv
Set to #EXIT_FAILURE on error.

References GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_OK, GNUNET_SCHEDULER_shutdown(), and MainParams::rv.

Referenced by loop_run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ loop_run()

static void loop_run ( void *  cls)
static

Main function to run the test cases.

Parameters
clsa struct MainParams *

Definition at line 426 of file testing_api_loop.c.

427 {
428  struct MainParams *mp = cls;
429 
431  mp->timeout,
432  &handle_result,
433  mp);
434 }
struct GNUNET_TIME_Relative timeout
Global timeout for the test.
struct GNUNET_TESTING_Command * commands
NULL-label terminated array of commands.
void GNUNET_TESTING_run(struct GNUNET_TESTING_Command *commands, struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_ResultCallback rc, void *rc_cls)
Run the testsuite.
static void handle_result(void *cls, enum GNUNET_GenericReturnValue rv)
Function called with the final result of the test.

References MainParams::commands, GNUNET_TESTING_run(), handle_result(), and MainParams::timeout.

Referenced by GNUNET_TESTING_main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_TESTING_main()

int GNUNET_TESTING_main ( struct GNUNET_TESTING_Command commands,
struct GNUNET_TIME_Relative  timeout 
)

Start a GNUnet scheduler event loop and run the testsuite.

Return 0 upon success. Expected to be called directly from main().

Parameters
commandsthe list of command to execute
timeouthow long to wait for each command to execute
Returns
EXIT_SUCCESS on success, EXIT_FAILURE on failure

Definition at line 438 of file testing_api_loop.c.

440 {
441  struct MainParams mp = {
442  .commands = commands,
443  .timeout = timeout,
444  .rv = EXIT_SUCCESS
445  };
446 
448  &mp);
449  return mp.rv;
450 }
void GNUNET_SCHEDULER_run(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Initialize and run scheduler.
Definition: scheduler.c:720
static void loop_run(void *cls)
Main function to run the test cases.

References commands, MainParams::commands, GNUNET_SCHEDULER_run(), loop_run(), MainParams::rv, and timeout.

Here is the call graph for this function:

◆ GNUNET_TESTING_async_fail()

void GNUNET_TESTING_async_fail ( struct GNUNET_TESTING_AsyncContext ac)

The asynchronous command of ac has failed.

Parameters
accommand-specific context

Definition at line 454 of file testing_api_loop.c.

455 {
456  GNUNET_assert (GNUNET_NO == ac->finished);
457  ac->finished = GNUNET_SYSERR;
459  if (NULL != ac->cont)
460  {
461  ac->cont (ac->cont_cls);
462  ac->cont = NULL;
463  }
464 }
static struct GNUNET_MQ_Envelope * ac
Handle to current GNUNET_PEERINFO_add_peer() operation.
void GNUNET_TESTING_interpreter_fail(struct GNUNET_TESTING_Interpreter *is)
Current command failed, clean up and fail the test case.

References ac, GNUNET_assert, GNUNET_NO, GNUNET_SYSERR, and GNUNET_TESTING_interpreter_fail().

Referenced by child_completed_callback(), and timeout_finish().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GNUNET_TESTING_async_finish()

void GNUNET_TESTING_async_finish ( struct GNUNET_TESTING_AsyncContext ac)

The asynchronous command of ac has finished.

Parameters
accommand-specific context

Definition at line 468 of file testing_api_loop.c.

469 {
470  GNUNET_assert (GNUNET_NO == ac->finished);
471  ac->finished = GNUNET_OK;
472  if (NULL != ac->cont)
473  {
474  ac->cont (ac->cont_cls);
475  ac->cont = NULL;
476  }
477 }

References ac, GNUNET_assert, GNUNET_NO, and GNUNET_OK.

Referenced by child_completed_callback(), done_finish(), hello_iter_cb(), helper_mst(), notify_connect(), and run_finish().

Here is the caller graph for this function: