aboutsummaryrefslogtreecommitdiff
path: root/src/testing
diff options
context:
space:
mode:
authorChristian Grothoff <grothoff@gnunet.org>2021-10-04 18:15:21 +0200
committerChristian Grothoff <grothoff@gnunet.org>2021-10-04 18:15:21 +0200
commit23b5cf23674d557864284eff81d876ee1b5631bf (patch)
tree2cdabbf345395d0bbcd3e415ff2386d53a30d0d7 /src/testing
parentf146e80752e73247acb9d6c7463188a82d26a774 (diff)
downloadgnunet-23b5cf23674d557864284eff81d876ee1b5631bf.tar.gz
gnunet-23b5cf23674d557864284eff81d876ee1b5631bf.zip
-basic santiy for testing API, breaks transport/ build
Diffstat (limited to 'src/testing')
-rw-r--r--src/testing/Makefile.am6
-rw-r--r--src/testing/test_testing_plugin_testcmd.c19
-rw-r--r--src/testing/testing.h94
-rw-r--r--src/testing/testing_api_cmd_batch.c64
-rw-r--r--src/testing/testing_api_cmd_end.c39
-rw-r--r--src/testing/testing_api_loop.c290
6 files changed, 286 insertions, 226 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 3e0d4d443..2bb03d157 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -42,9 +42,11 @@ libgnunet_test_testing_plugin_testcmd_la_LIBADD = \
42libgnunet_test_testing_plugin_testcmd_la_LDFLAGS = \ 42libgnunet_test_testing_plugin_testcmd_la_LDFLAGS = \
43 $(GN_PLUGIN_LDFLAGS) 43 $(GN_PLUGIN_LDFLAGS)
44 44
45# testing_api_cmd_finish.c
46
45libgnunettesting_la_SOURCES = \ 47libgnunettesting_la_SOURCES = \
48 testing_api_cmd_end.c \
46 testing_api_cmd_local_test_finished.c \ 49 testing_api_cmd_local_test_finished.c \
47 testing_api_cmd_finish.c \
48 testing_api_cmd_send_peer_ready.c \ 50 testing_api_cmd_send_peer_ready.c \
49 testing_api_cmd_block_until_all_peers_started.c \ 51 testing_api_cmd_block_until_all_peers_started.c \
50 testing_api_cmd_block_until_external_trigger.c \ 52 testing_api_cmd_block_until_external_trigger.c \
@@ -56,7 +58,7 @@ libgnunettesting_la_SOURCES = \
56 testing_api_cmd_netjail_stop_testsystem_v2.c \ 58 testing_api_cmd_netjail_stop_testsystem_v2.c \
57 testing_api_cmd_netjail_stop.c \ 59 testing_api_cmd_netjail_stop.c \
58 testing_api_cmd_netjail_stop_v2.c \ 60 testing_api_cmd_netjail_stop_v2.c \
59 testing.c testing.h \ 61 testing.c \
60 testing_api_cmd_system_create.c \ 62 testing_api_cmd_system_create.c \
61 testing_api_cmd_system_destroy.c \ 63 testing_api_cmd_system_destroy.c \
62 testing_api_cmd_batch.c \ 64 testing_api_cmd_batch.c \
diff --git a/src/testing/test_testing_plugin_testcmd.c b/src/testing/test_testing_plugin_testcmd.c
index 444272fcd..32e2b38a7 100644
--- a/src/testing/test_testing_plugin_testcmd.c
+++ b/src/testing/test_testing_plugin_testcmd.c
@@ -17,11 +17,12 @@
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19 */ 19 */
20
21/** 20/**
22 * @file testbed/plugin_testcmd.c 21 * @file testbed/plugin_testcmd.c
23 * @brief a plugin to provide the API for running test cases. 22 * @brief a plugin to provide the API for running test cases.
24 * @author t3sserakt 23 * @author t3sserakt
24 *
25 * // FIXME: too verbose, no logic to return final status, will segv!
25 */ 26 */
26#include "platform.h" 27#include "platform.h"
27#include "gnunet_testing_ng_lib.h" 28#include "gnunet_testing_ng_lib.h"
@@ -33,8 +34,11 @@
33 */ 34 */
34#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__) 35#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
35 36
37
38// FIXME: bad global!
36unsigned int are_all_peers_started; 39unsigned int are_all_peers_started;
37 40
41
38static void 42static void
39all_peers_started () 43all_peers_started ()
40{ 44{
@@ -44,8 +48,10 @@ all_peers_started ()
44 are_all_peers_started); 48 are_all_peers_started);
45} 49}
46 50
51
47static void 52static void
48start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip, 53start_testcase (TESTING_CMD_HELPER_write_cb write_message,
54 char *router_ip,
49 char *node_ip, 55 char *node_ip,
50 char *n, 56 char *n,
51 char *m, 57 char *m,
@@ -70,9 +76,10 @@ start_testcase (TESTING_CMD_HELPER_write_cb write_message, char *router_ip,
70 write_message) 76 write_message)
71 }; 77 };
72 78
73 GNUNET_TESTING_run (NULL, 79 GNUNET_TESTING_run (commands,
74 commands, 80 GNUNET_TIME_UNIT_FOREVER_REL,
75 GNUNET_TIME_UNIT_FOREVER_REL); 81 NULL, /* FIXME: pass continuation! */
82 NULL);
76 LOG (GNUNET_ERROR_TYPE_ERROR, 83 LOG (GNUNET_ERROR_TYPE_ERROR,
77 "We got here 7!\n"); 84 "We got here 7!\n");
78 85
@@ -113,4 +120,4 @@ libgnunet_plugin_testcmd_done (void *cls)
113} 120}
114 121
115 122
116/* end of plugin_testcmd.c */ 123
diff --git a/src/testing/testing.h b/src/testing/testing.h
index b12466530..8aba09e4b 100644
--- a/src/testing/testing.h
+++ b/src/testing/testing.h
@@ -21,54 +21,54 @@
21/** 21/**
22 * @author t3sserakt 22 * @author t3sserakt
23 */ 23 */
24 24#ifndef TESTING_H
25#define TESTING_H
25#include "gnunet_util_lib.h" 26#include "gnunet_util_lib.h"
26 27
28
29/**
30 * Advance internal pointer to next command.
31 *
32 * @param cls batch internal state
33 * @return true if we could advance, false if the batch
34 * has completed and cannot advance anymore
35 */
36bool
37GNUNET_TESTING_cmd_batch_next_ (void *cls);
38
39
40/**
41 * Test if this command is a batch command.
42 *
43 * @return false if not, true if it is a batch command
44 */
45bool
46GNUNET_TESTING_cmd_is_batch_ (const struct GNUNET_TESTING_Command *cmd);
47
48
49/**
50 * Obtain what command the batch is at.
51 *
52 * @return cmd current batch command
53 */
54struct GNUNET_TESTING_Command *
55GNUNET_TESTING_cmd_batch_get_current_ (const struct GNUNET_TESTING_Command *cmd);
56
57
27/** 58/**
28 * Global state of the interpreter, used by a command 59 * Set what command the batch should be at. Needed for
29 * to access information about other commands. 60 * loops. We may want to change this to take a label
61 * and/or expose it in the public API in the future.
62 * Not used for now.
63 *
64 * @param cmd current batch command
65 * @param new_ip where to move the IP
30 */ 66 */
31// SUGGESTION: consider making this struct opaque (only known inside of libgnunettesting, 67void
32// say main loop and a few select commands, like next/fail/batch); + helper 68GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
33// function to access 'cfg'? 69 unsigned int new_ip);
34struct GNUNET_TESTING_Interpreter 70
35{ 71
36 72
37 /** 73
38 * Commands the interpreter will run. 74#endif
39 */
40 struct GNUNET_TESTING_Command *commands;
41
42 /**
43 * Interpreter task (if one is scheduled).
44 */
45 struct GNUNET_SCHEDULER_Task *task;
46
47 /**
48 * Finish task of a blocking call to a commands finish method.
49 */
50 struct GNUNET_SCHEDULER_Task *finish_task;
51
52 /**
53 * Our configuration.
54 */
55 const struct GNUNET_CONFIGURATION_Handle *cfg;
56
57 /**
58 * Task run on timeout.
59 */
60 struct GNUNET_SCHEDULER_Task *timeout_task;
61
62 /**
63 * Instruction pointer. Tells #interpreter_run() which instruction to run
64 * next. Need (signed) int because it gets -1 when rewinding the
65 * interpreter to the first CMD.
66 */
67 int ip;
68
69 /**
70 * Result of the testcases, #GNUNET_OK on success
71 */
72 int result;
73
74};
diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c
index e39489616..080a4880d 100644
--- a/src/testing/testing_api_cmd_batch.c
+++ b/src/testing/testing_api_cmd_batch.c
@@ -119,16 +119,15 @@ batch_traits (void *cls,
119 const char *trait, 119 const char *trait,
120 unsigned int index) 120 unsigned int index)
121{ 121{
122 struct BatchState *bs = cls;
123 // FIXME: these constants should be more global!
122#define CURRENT_CMD_INDEX 0 124#define CURRENT_CMD_INDEX 0
123#define BATCH_INDEX 1 125#define BATCH_INDEX 1
124
125 struct BatchState *bs = cls;
126
127 struct GNUNET_TESTING_Trait traits[] = { 126 struct GNUNET_TESTING_Trait traits[] = {
128 GNUNET_TESTING_make_trait_cmd 127 GNUNET_TESTING_make_trait_cmd (CURRENT_CMD_INDEX,
129 (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]), 128 &bs->batch[bs->batch_ip]),
130 GNUNET_TESTING_make_trait_cmd 129 GNUNET_TESTING_make_trait_cmd (BATCH_INDEX,
131 (BATCH_INDEX, bs->batch), 130 bs->batch),
132 GNUNET_TESTING_trait_end () 131 GNUNET_TESTING_trait_end ()
133 }; 132 };
134 133
@@ -185,68 +184,45 @@ GNUNET_TESTING_cmd_batch (const char *label,
185} 184}
186 185
187 186
188/** 187bool
189 * Advance internal pointer to next command. 188GNUNET_TESTING_cmd_batch_next_ (void *cls)
190 *
191 * @param is interpreter state.
192 */
193void
194GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is)
195{ 189{
196 struct BatchState *bs = is->commands[is->ip].cls; 190 struct BatchState *bs = cls;
197 191
198 if (NULL == bs->batch[bs->batch_ip].label) 192 if (NULL == bs->batch[bs->batch_ip].label)
199 { 193 return false;
200 is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get (); 194 bs->batch[bs->batch_ip].finish_time
201 is->ip++; 195 = GNUNET_TIME_absolute_get ();
202 return;
203 }
204 bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
205 bs->batch_ip++; 196 bs->batch_ip++;
197 return true;
206} 198}
207 199
208 200
209/** 201bool
210 * Test if this command is a batch command. 202GNUNET_TESTING_cmd_is_batch_ (const struct GNUNET_TESTING_Command *cmd)
211 *
212 * @return false if not, true if it is a batch command
213 */
214int
215GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd)
216{ 203{
217 return cmd->run == &batch_run; 204 return cmd->run == &batch_run;
218} 205}
219 206
220 207
221/**
222 * Obtain what command the batch is at.
223 *
224 * @return cmd current batch command
225 */
226struct GNUNET_TESTING_Command * 208struct GNUNET_TESTING_Command *
227GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd) 209GNUNET_TESTING_cmd_batch_get_current_ (const struct GNUNET_TESTING_Command *cmd)
228{ 210{
229 struct BatchState *bs = cmd->cls; 211 struct BatchState *bs = cmd->cls;
230 212
231 GNUNET_assert (cmd->run == &batch_run); 213 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
232 return &bs->batch[bs->batch_ip]; 214 return &bs->batch[bs->batch_ip];
233} 215}
234 216
235 217
236/**
237 * Set what command the batch should be at.
238 *
239 * @param cmd current batch command
240 * @param new_ip where to move the IP
241 */
242void 218void
243GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd, 219GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
244 unsigned int new_ip) 220 unsigned int new_ip)
245{ 221{
246 struct BatchState *bs = cmd->cls; 222 struct BatchState *bs = cmd->cls;
247 223
248 /* sanity checks */ 224 /* sanity checks */
249 GNUNET_assert (cmd->run == &batch_run); 225 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
250 for (unsigned int i = 0; i < new_ip; i++) 226 for (unsigned int i = 0; i < new_ip; i++)
251 GNUNET_assert (NULL != bs->batch[i].label); 227 GNUNET_assert (NULL != bs->batch[i].label);
252 /* actual logic */ 228 /* actual logic */
diff --git a/src/testing/testing_api_cmd_end.c b/src/testing/testing_api_cmd_end.c
new file mode 100644
index 000000000..f0f036429
--- /dev/null
+++ b/src/testing/testing_api_cmd_end.c
@@ -0,0 +1,39 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file testing/testing_api_cmd_end.c
22 * @brief command to end a command array
23 */
24#include "platform.h"
25#include "gnunet_util_lib.h"
26#include "gnunet_testing_ng_lib.h"
27
28
29struct GNUNET_TESTING_Command
30GNUNET_TESTING_cmd_end (void)
31{
32 static struct GNUNET_TESTING_Command cmd = {
33 .label = NULL
34 };
35
36 return cmd;
37}
38
39
diff --git a/src/testing/testing_api_loop.c b/src/testing/testing_api_loop.c
index 1c8eb1db6..b21e01fcc 100644
--- a/src/testing/testing_api_loop.c
+++ b/src/testing/testing_api_loop.c
@@ -24,25 +24,64 @@
24 * @author Christian Grothoff (GNU Taler testing) 24 * @author Christian Grothoff (GNU Taler testing)
25 * @author Marcello Stanisci (GNU Taler testing) 25 * @author Marcello Stanisci (GNU Taler testing)
26 * @author t3sserakt 26 * @author t3sserakt
27 *
28 * FIXME:
29 * - interpreter failure is NOT returned properly yet!
30 * - abuse of shutdown logic for interpreter termination
31 * => API design flaw to be fixed!
32 */ 27 */
33#include "platform.h" 28#include "platform.h"
34#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
35#include "gnunet_testing_ng_lib.h" 30#include "gnunet_testing_ng_lib.h"
36#include "testing.h" 31#include "testing.h"
37 32
38
39/** 33/**
40 * Lookup command by label. 34 * Global state of the interpreter, used by a command
41 * 35 * to access information about other commands.
42 * @param is interpreter to lookup command in
43 * @param label label to look for
44 * @return NULL if command was not found
45 */ 36 */
37struct GNUNET_TESTING_Interpreter
38{
39
40 /**
41 * Function to call with the test result.
42 */
43 GNUNET_TESTING_ResultCallback rc;
44
45 /**
46 * Closure for @e rc.
47 */
48 void *rc_cls;
49
50 /**
51 * Commands the interpreter will run.
52 */
53 struct GNUNET_TESTING_Command *commands;
54
55 /**
56 * Interpreter task (if one is scheduled).
57 */
58 struct GNUNET_SCHEDULER_Task *task;
59
60 /**
61 * Final task that returns the result.
62 */
63 struct GNUNET_SCHEDULER_Task *final_task;
64
65 /**
66 * Task run on timeout.
67 */
68 struct GNUNET_SCHEDULER_Task *timeout_task;
69
70 /**
71 * Instruction pointer. Tells #interpreter_run() which instruction to run
72 * next. Need (signed) int because it gets -1 when rewinding the
73 * interpreter to the first CMD.
74 */
75 int ip;
76
77 /**
78 * Result of the testcases, #GNUNET_OK on success
79 */
80 enum GNUNET_GenericReturnValue result;
81
82};
83
84
46const struct GNUNET_TESTING_Command * 85const struct GNUNET_TESTING_Command *
47GNUNET_TESTING_interpreter_lookup_command ( 86GNUNET_TESTING_interpreter_lookup_command (
48 struct GNUNET_TESTING_Interpreter *is, 87 struct GNUNET_TESTING_Interpreter *is,
@@ -65,7 +104,7 @@ GNUNET_TESTING_interpreter_lookup_command (
65 label)) ) 104 label)) )
66 return cmd; 105 return cmd;
67 106
68 if (GNUNET_TESTING_cmd_is_batch (cmd)) 107 if (GNUNET_TESTING_cmd_is_batch_ (cmd))
69 { 108 {
70#define BATCH_INDEX 1 109#define BATCH_INDEX 1
71 struct GNUNET_TESTING_Command *batch; 110 struct GNUNET_TESTING_Command *batch;
@@ -73,7 +112,7 @@ GNUNET_TESTING_interpreter_lookup_command (
73 struct GNUNET_TESTING_Command *icmd; 112 struct GNUNET_TESTING_Command *icmd;
74 const struct GNUNET_TESTING_Command *match; 113 const struct GNUNET_TESTING_Command *match;
75 114
76 current = GNUNET_TESTING_cmd_batch_get_current (cmd); 115 current = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
77 GNUNET_assert (GNUNET_OK == 116 GNUNET_assert (GNUNET_OK ==
78 GNUNET_TESTING_get_trait_cmd (cmd, 117 GNUNET_TESTING_get_trait_cmd (cmd,
79 BATCH_INDEX, 118 BATCH_INDEX,
@@ -96,10 +135,58 @@ GNUNET_TESTING_interpreter_lookup_command (
96 } 135 }
97 } 136 }
98 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 137 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
99 "Command not found: %s\n", 138 "Command `%s' not found\n",
100 label); 139 label);
101 return NULL; 140 return NULL;
141}
142
143
144/**
145 * Finish the test run, return the final result.
146 *
147 * @param cls the `struct GNUNET_TESTING_Interpreter`
148 */
149static void
150finish_test (void *cls)
151{
152 struct GNUNET_TESTING_Interpreter *is = cls;
153 struct GNUNET_TESTING_Command *cmd;
154 const char *label;
102 155
156 is->final_task = NULL;
157 label = is->commands[is->ip].label;
158 if (NULL == label)
159 label = "END";
160 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
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 {
168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
169 "Cleaning up cmd %s\n",
170 cmd->label);
171 cmd->cleanup (cmd->cls);
172 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
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);
103} 190}
104 191
105 192
@@ -125,15 +212,10 @@ interpreter_next (void *cls)
125 212
126 if (GNUNET_SYSERR == is->result) 213 if (GNUNET_SYSERR == is->result)
127 return; /* ignore, we already failed! */ 214 return; /* ignore, we already failed! */
128 if (GNUNET_TESTING_cmd_is_batch (cmd)) 215 cmd->finish_time = GNUNET_TIME_absolute_get ();
129 { 216 if ( (! GNUNET_TESTING_cmd_is_batch_ (cmd)) ||
130 GNUNET_TESTING_cmd_batch_next (is); 217 (! GNUNET_TESTING_cmd_batch_next_ (cmd->cls)) )
131 }
132 else
133 {
134 cmd->finish_time = GNUNET_TIME_absolute_get ();
135 is->ip++; 218 is->ip++;
136 }
137 if (0 == (ipc % 1000)) 219 if (0 == (ipc % 1000))
138 { 220 {
139 if (0 != ipc) 221 if (0 != ipc)
@@ -150,26 +232,24 @@ interpreter_next (void *cls)
150} 232}
151 233
152 234
153/**
154 * Current command failed, clean up and fail the test case.
155 *
156 * @param is interpreter of the test
157 */
158void 235void
159GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is) 236GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
160{ 237{
161 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip]; 238 struct GNUNET_TESTING_Command *cmd = &is->commands[is->ip];
162 239
163 if (GNUNET_SYSERR == is->result) 240 if (GNUNET_SYSERR == is->result)
241 {
242 GNUNET_break (0);
164 return; /* ignore, we already failed! */ 243 return; /* ignore, we already failed! */
244 }
165 if (NULL != cmd) 245 if (NULL != cmd)
166 { 246 {
167 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 247 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
168 "Failed at command `%s'\n", 248 "Failed at command `%s'\n",
169 cmd->label); 249 cmd->label);
170 while (GNUNET_TESTING_cmd_is_batch (cmd)) 250 while (GNUNET_TESTING_cmd_is_batch_ (cmd))
171 { 251 {
172 cmd = GNUNET_TESTING_cmd_batch_get_current (cmd); 252 cmd = GNUNET_TESTING_cmd_batch_get_current_ (cmd);
173 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
174 "Failed in batch at command `%s'\n", 254 "Failed in batch at command `%s'\n",
175 cmd->label); 255 cmd->label);
@@ -181,29 +261,12 @@ GNUNET_TESTING_interpreter_fail (struct GNUNET_TESTING_Interpreter *is)
181 "Failed with CMD being NULL!\n"); 261 "Failed with CMD being NULL!\n");
182 } 262 }
183 is->result = GNUNET_SYSERR; 263 is->result = GNUNET_SYSERR;
184 GNUNET_SCHEDULER_shutdown (); 264 GNUNET_assert (NULL == is->final_task);
185} 265 is->final_task = GNUNET_SCHEDULER_add_now (&finish_test,
186 266 is);
187
188/**
189 * Create command array terminator.
190 *
191 * @return a end-command.
192 */
193struct GNUNET_TESTING_Command
194GNUNET_TESTING_cmd_end (void)
195{
196 static struct GNUNET_TESTING_Command cmd = {
197 .label = NULL
198 };
199
200 return cmd;
201} 267}
202 268
203 269
204/**
205 * Obtain current label.
206 */
207const char * 270const char *
208GNUNET_TESTING_interpreter_get_current_label ( 271GNUNET_TESTING_interpreter_get_current_label (
209 struct GNUNET_TESTING_Interpreter *is) 272 struct GNUNET_TESTING_Interpreter *is)
@@ -234,12 +297,9 @@ interpreter_run (void *cls)
234 GNUNET_SCHEDULER_shutdown (); 297 GNUNET_SCHEDULER_shutdown ();
235 return; 298 return;
236 } 299 }
237 if (NULL != cmd) 300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
238 { 301 "Running command `%s'\n",
239 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 302 cmd->label);
240 "Running command `%s'\n",
241 cmd->label);
242 }
243 cmd->start_time 303 cmd->start_time
244 = cmd->last_req_time 304 = cmd->last_req_time
245 = GNUNET_TIME_absolute_get (); 305 = GNUNET_TIME_absolute_get ();
@@ -261,57 +321,6 @@ interpreter_run (void *cls)
261 321
262 322
263/** 323/**
264 * Function run when the test terminates (good or bad).
265 * Cleans up our state.
266 *
267 * @param cls the interpreter state.
268 */
269static void
270do_shutdown (void *cls)
271{
272 struct GNUNET_TESTING_Interpreter *is = cls;
273 struct GNUNET_TESTING_Command *cmd;
274 const char *label;
275
276 label = is->commands[is->ip].label;
277 if (NULL == label)
278 label = "END";
279 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
280 "Executing shutdown at `%s'\n",
281 label);
282 for (unsigned int j = 0;
283 NULL != (cmd = &is->commands[j])->label;
284 j++)
285 {
286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
287 "Cleaning up cmd %s\n",
288 cmd->label);
289 cmd->cleanup (cmd->cls);
290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
291 "Cleaned up cmd %s\n",
292 cmd->label);
293 }
294 if (NULL != is->finish_task)
295 {
296 GNUNET_SCHEDULER_cancel (is->finish_task);
297 is->finish_task = NULL;
298 }
299 if (NULL != is->task)
300 {
301 GNUNET_SCHEDULER_cancel (is->task);
302 is->task = NULL;
303 }
304 if (NULL != is->timeout_task)
305 {
306 GNUNET_SCHEDULER_cancel (is->timeout_task);
307 is->timeout_task = NULL;
308 }
309 GNUNET_free (is->commands);
310 GNUNET_free (is);
311}
312
313
314/**
315 * Function run when the test terminates (good or bad) with timeout. 324 * Function run when the test terminates (good or bad) with timeout.
316 * 325 *
317 * @param cls the interpreter state 326 * @param cls the interpreter state
@@ -323,20 +332,24 @@ do_timeout (void *cls)
323 332
324 is->timeout_task = NULL; 333 is->timeout_task = NULL;
325 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 334 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
326 "Terminating test due to timeout\n"); 335 "Terminating test due to global timeout\n");
327 GNUNET_SCHEDULER_shutdown (); 336 is->result = GNUNET_SYSERR;
337 finish_test (is);
328} 338}
329 339
330 340
331enum GNUNET_GenericReturnValue 341void
332GNUNET_TESTING_run (const char *cfg_filename, 342GNUNET_TESTING_run (struct GNUNET_TESTING_Command *commands,
333 struct GNUNET_TESTING_Command *commands, 343 struct GNUNET_TIME_Relative timeout,
334 struct GNUNET_TIME_Relative timeout) 344 GNUNET_TESTING_ResultCallback rc,
345 void *rc_cls)
335{ 346{
336 struct GNUNET_TESTING_Interpreter *is; 347 struct GNUNET_TESTING_Interpreter *is;
337 unsigned int i; 348 unsigned int i;
338 349
339 is = GNUNET_new (struct GNUNET_TESTING_Interpreter); 350 is = GNUNET_new (struct GNUNET_TESTING_Interpreter);
351 is->rc = rc;
352 is->rc_cls = rc_cls;
340 /* get the number of commands */ 353 /* get the number of commands */
341 for (i = 0; NULL != commands[i].label; i++) 354 for (i = 0; NULL != commands[i].label; i++)
342 ; 355 ;
@@ -349,11 +362,8 @@ GNUNET_TESTING_run (const char *cfg_filename,
349 = GNUNET_SCHEDULER_add_delayed (timeout, 362 = GNUNET_SCHEDULER_add_delayed (timeout,
350 &do_timeout, 363 &do_timeout,
351 is); 364 is);
352 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
353 is);
354 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run, 365 is->task = GNUNET_SCHEDULER_add_now (&interpreter_run,
355 is); 366 is);
356 return GNUNET_OK;
357} 367}
358 368
359 369
@@ -362,14 +372,46 @@ GNUNET_TESTING_run (const char *cfg_filename,
362 */ 372 */
363struct MainParams 373struct MainParams
364{ 374{
365 const char *cfg_filename; 375
376 /**
377 * NULL-label terminated array of commands.
378 */
366 struct GNUNET_TESTING_Command *commands; 379 struct GNUNET_TESTING_Command *commands;
380
381 /**
382 * Global timeout for the test.
383 */
367 struct GNUNET_TIME_Relative timeout; 384 struct GNUNET_TIME_Relative timeout;
385
386 /**
387 * Set to #EXIT_FAILURE on error.
388 */
368 int rv; 389 int rv;
369}; 390};
370 391
371 392
372/** 393/**
394 * Function called with the final result of the test.
395 *
396 * @param cls the `struct MainParams`
397 * @param rv #GNUNET_OK if the test passed
398 */
399static void
400handle_result (void *cls,
401 enum GNUNET_GenericReturnValue rv)
402{
403 struct MainParams *mp = cls;
404
405 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
406 "Test exits with status %d\n",
407 rv);
408 if (GNUNET_OK != rv)
409 mp->rv = EXIT_FAILURE;
410 GNUNET_SCHEDULER_shutdown ();
411}
412
413
414/**
373 * Main function to run the test cases. 415 * Main function to run the test cases.
374 * 416 *
375 * @param cls a `struct MainParams *` 417 * @param cls a `struct MainParams *`
@@ -379,24 +421,18 @@ loop_run (void *cls)
379{ 421{
380 struct MainParams *mp = cls; 422 struct MainParams *mp = cls;
381 423
382 if (GNUNET_OK != 424 GNUNET_TESTING_run (mp->commands,
383 GNUNET_TESTING_run (mp->cfg_filename, 425 mp->timeout,
384 mp->commands, 426 &handle_result,
385 mp->timeout)) 427 mp);
386 {
387 GNUNET_break (0);
388 mp->rv = EXIT_FAILURE;
389 }
390} 428}
391 429
392 430
393int 431int
394GNUNET_TESTING_main (const char *cfg_filename, 432GNUNET_TESTING_main (struct GNUNET_TESTING_Command *commands,
395 struct GNUNET_TESTING_Command *commands,
396 struct GNUNET_TIME_Relative timeout) 433 struct GNUNET_TIME_Relative timeout)
397{ 434{
398 struct MainParams mp = { 435 struct MainParams mp = {
399 .cfg_filename = cfg_filename,
400 .commands = commands, 436 .commands = commands,
401 .timeout = timeout, 437 .timeout = timeout,
402 .rv = EXIT_SUCCESS 438 .rv = EXIT_SUCCESS