aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_batch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_api_cmd_batch.c')
-rw-r--r--src/testing/testing_api_cmd_batch.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/testing/testing_api_cmd_batch.c b/src/testing/testing_api_cmd_batch.c
new file mode 100644
index 000000000..74a763718
--- /dev/null
+++ b/src/testing/testing_api_cmd_batch.c
@@ -0,0 +1,257 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008, 2009, 2012 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/**
22 * @file testing/testing_api_cmd_batch.c
23 * @brief Implement batch-execution of CMDs.
24 * @author Marcello Stanisci (GNU Taler testing)
25 * @author t3sserakt
26 */
27#include "platform.h"
28#include "gnunet_testing_ng_lib.h"
29
30
31/**
32 * State for a "batch" CMD.
33 */
34struct BatchState
35{
36 /**
37 * CMDs batch.
38 */
39 struct GNUNET_TESTING_Command *batch;
40
41 /**
42 * Internal command pointer.
43 */
44 unsigned int batch_ip;
45};
46
47
48/**
49 * Run the command.
50 *
51 * @param cls closure.
52 * @param cmd the command being executed.
53 * @param is the interpreter state.
54 */
55static void
56batch_run (void *cls,
57 const struct GNUNET_TESTING_Command *cmd,
58 struct GNUNET_TESTING_Interpreter *is)
59{
60 struct BatchState *bs = cls;
61
62 if (NULL != bs->batch[bs->batch_ip].label)
63 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
64 "Running batched command: %s\n",
65 bs->batch[bs->batch_ip].label);
66
67 /* hit end command, leap to next top-level command. */
68 if (NULL == bs->batch[bs->batch_ip].label)
69 {
70 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
71 "Exiting from batch: %s\n",
72 cmd->label);
73 GNUNET_TESTING_interpreter_next (is);
74 return;
75 }
76 bs->batch[bs->batch_ip].start_time
77 = bs->batch[bs->batch_ip].last_req_time
78 = GNUNET_TIME_absolute_get ();
79 bs->batch[bs->batch_ip].num_tries = 1;
80 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
81 &bs->batch[bs->batch_ip],
82 is);
83}
84
85
86/**
87 * Cleanup the state from a "reserve status" CMD, and possibly
88 * cancel a pending operation thereof.
89 *
90 * @param cls closure.
91 * @param cmd the command which is being cleaned up.
92 */
93static void
94batch_cleanup (void *cls,
95 const struct GNUNET_TESTING_Command *cmd)
96{
97 struct BatchState *bs = cls;
98
99 (void) cmd;
100 for (unsigned int i = 0;
101 NULL != bs->batch[i].label;
102 i++)
103 bs->batch[i].cleanup (bs->batch[i].cls,
104 &bs->batch[i]);
105 GNUNET_free (bs->batch);
106 GNUNET_free (bs);
107}
108
109
110/**
111 * Offer internal data from a "batch" CMD, to other commands.
112 *
113 * @param cls closure.
114 * @param[out] ret result.
115 * @param trait name of the trait.
116 * @param index index number of the object to offer.
117 * @return #GNUNET_OK on success.
118 */
119static int
120batch_traits (void *cls,
121 const void **ret,
122 const char *trait,
123 unsigned int index)
124{
125#define CURRENT_CMD_INDEX 0
126#define BATCH_INDEX 1
127
128 struct BatchState *bs = cls;
129
130 struct GNUNET_TESTING_Trait traits[] = {
131 GNUNET_TESTING_make_trait_cmd
132 (CURRENT_CMD_INDEX, &bs->batch[bs->batch_ip]),
133 GNUNET_TESTING_make_trait_cmd
134 (BATCH_INDEX, bs->batch),
135 GNUNET_TESTING_trait_end ()
136 };
137
138 /* Always return current command. */
139 return GNUNET_TESTING_get_trait (traits,
140 ret,
141 trait,
142 index);
143}
144
145
146/**
147 * Create a "batch" command. Such command takes a
148 * end_CMD-terminated array of CMDs and executed them.
149 * Once it hits the end CMD, it passes the control
150 * to the next top-level CMD, regardless of it being
151 * another batch or ordinary CMD.
152 *
153 * @param label the command label.
154 * @param batch array of CMDs to execute.
155 *
156 * @return the command.
157 */
158struct GNUNET_TESTING_Command
159GNUNET_TESTING_cmd_batch (const char *label,
160 struct GNUNET_TESTING_Command *batch)
161{
162 struct BatchState *bs;
163 unsigned int i;
164
165 bs = GNUNET_new (struct BatchState);
166
167 /* Get number of commands. */
168 for (i = 0; NULL != batch[i].label; i++)
169 /* noop */
170 ;
171
172 bs->batch = GNUNET_new_array (i + 1,
173 struct GNUNET_TESTING_Command);
174 memcpy (bs->batch,
175 batch,
176 sizeof (struct GNUNET_TESTING_Command) * i);
177 {
178 struct GNUNET_TESTING_Command cmd = {
179 .cls = bs,
180 .label = label,
181 .run = &batch_run,
182 .cleanup = &batch_cleanup,
183 .traits = &batch_traits
184 };
185
186 return cmd;
187 }
188}
189
190
191/**
192 * Advance internal pointer to next command.
193 *
194 * @param is interpreter state.
195 */
196void
197GNUNET_TESTING_cmd_batch_next (struct GNUNET_TESTING_Interpreter *is)
198{
199 struct BatchState *bs = is->commands[is->ip].cls;
200
201 if (NULL == bs->batch[bs->batch_ip].label)
202 {
203 is->commands[is->ip].finish_time = GNUNET_TIME_absolute_get ();
204 is->ip++;
205 return;
206 }
207 bs->batch[bs->batch_ip].finish_time = GNUNET_TIME_absolute_get ();
208 bs->batch_ip++;
209}
210
211
212/**
213 * Test if this command is a batch command.
214 *
215 * @return false if not, true if it is a batch command
216 */
217int
218GNUNET_TESTING_cmd_is_batch (const struct GNUNET_TESTING_Command *cmd)
219{
220 return cmd->run == &batch_run;
221}
222
223
224/**
225 * Obtain what command the batch is at.
226 *
227 * @return cmd current batch command
228 */
229struct GNUNET_TESTING_Command *
230GNUNET_TESTING_cmd_batch_get_current (const struct GNUNET_TESTING_Command *cmd)
231{
232 struct BatchState *bs = cmd->cls;
233
234 GNUNET_assert (cmd->run == &batch_run);
235 return &bs->batch[bs->batch_ip];
236}
237
238
239/**
240 * Set what command the batch should be at.
241 *
242 * @param cmd current batch command
243 * @param new_ip where to move the IP
244 */
245void
246GNUNET_TESTING_cmd_batch_set_current (const struct GNUNET_TESTING_Command *cmd,
247 unsigned int new_ip)
248{
249 struct BatchState *bs = cmd->cls;
250
251 /* sanity checks */
252 GNUNET_assert (cmd->run == &batch_run);
253 for (unsigned int i = 0; i < new_ip; i++)
254 GNUNET_assert (NULL != bs->batch[i].label);
255 /* actual logic */
256 bs->batch_ip = new_ip;
257}