aboutsummaryrefslogtreecommitdiff
path: root/src/service/testing/testing_api_cmd_batch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/testing/testing_api_cmd_batch.c')
-rw-r--r--src/service/testing/testing_api_cmd_batch.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/service/testing/testing_api_cmd_batch.c b/src/service/testing/testing_api_cmd_batch.c
new file mode 100644
index 000000000..7dc990855
--- /dev/null
+++ b/src/service/testing/testing_api_cmd_batch.c
@@ -0,0 +1,223 @@
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/**
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#include "testing.h"
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 * Our label.
43 */
44 const char *label;
45
46 /**
47 * Internal command pointer.
48 */
49 unsigned int batch_ip;
50};
51
52
53/**
54 * Run the command.
55 *
56 * @param cls closure.
57 * @param is the interpreter state.
58 */
59static void
60batch_run (void *cls,
61 struct GNUNET_TESTING_Interpreter *is)
62{
63 struct BatchState *bs = cls;
64
65 if (NULL != bs->batch[bs->batch_ip].run)
66 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
67 "Running batched command: %s\n",
68 bs->batch[bs->batch_ip].label);
69
70 /* hit end command, leap to next top-level command. */
71 if (NULL == bs->batch[bs->batch_ip].run)
72 {
73 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
74 "Exiting from batch: %s\n",
75 bs->label);
76 return;
77 }
78 bs->batch[bs->batch_ip].start_time
79 = bs->batch[bs->batch_ip].last_req_time
80 = GNUNET_TIME_absolute_get ();
81 bs->batch[bs->batch_ip].num_tries = 1;
82 bs->batch[bs->batch_ip].run (bs->batch[bs->batch_ip].cls,
83 is);
84}
85
86
87/**
88 * Cleanup the state from a "reserve status" CMD, and possibly
89 * cancel a pending operation thereof.
90 *
91 * @param cls closure.
92 */
93static void
94batch_cleanup (void *cls)
95{
96 struct BatchState *bs = cls;
97
98 for (unsigned int i = 0;
99 NULL != bs->batch[i].run;
100 i++)
101 bs->batch[i].cleanup (bs->batch[i].cls);
102 GNUNET_free (bs->batch);
103 GNUNET_free (bs);
104}
105
106
107/**
108 * Offer internal data from a "batch" CMD, to other commands.
109 *
110 * @param cls closure.
111 * @param[out] ret result.
112 * @param trait name of the trait.
113 * @param index index number of the object to offer.
114 * @return #GNUNET_OK on success.
115 */
116static enum GNUNET_GenericReturnValue
117batch_traits (void *cls,
118 const void **ret,
119 const char *trait,
120 unsigned int index)
121{
122 struct BatchState *bs = cls;
123 // FIXME: these constants should be more global!
124#define CURRENT_CMD_INDEX 0
125#define BATCH_INDEX 1
126 struct GNUNET_TESTING_Trait traits[] = {
127 GNUNET_TESTING_make_trait_cmd (CURRENT_CMD_INDEX,
128 &bs->batch[bs->batch_ip]),
129 GNUNET_TESTING_make_trait_cmd (BATCH_INDEX,
130 bs->batch),
131 GNUNET_TESTING_trait_end ()
132 };
133
134 /* Always return current command. */
135 return GNUNET_TESTING_get_trait (traits,
136 ret,
137 trait,
138 index);
139}
140
141
142/**
143 * Create a "batch" command. Such command takes a
144 * end_CMD-terminated array of CMDs and executed them.
145 * Once it hits the end CMD, it passes the control
146 * to the next top-level CMD, regardless of it being
147 * another batch or ordinary CMD.
148 *
149 * @param label the command label.
150 * @param batch array of CMDs to execute.
151 *
152 * @return the command.
153 */
154struct GNUNET_TESTING_Command
155GNUNET_TESTING_cmd_batch (const char *label,
156 struct GNUNET_TESTING_Command *batch)
157{
158 struct BatchState *bs;
159 unsigned int i;
160
161 bs = GNUNET_new (struct BatchState);
162 bs->label = label;
163 /* Get number of commands. */
164 for (i = 0; NULL != batch[i].run; i++)
165 /* noop */
166 ;
167
168 bs->batch = GNUNET_new_array (i + 1,
169 struct GNUNET_TESTING_Command);
170 memcpy (bs->batch,
171 batch,
172 sizeof (struct GNUNET_TESTING_Command) * i);
173 return GNUNET_TESTING_command_new (bs, label,
174 &batch_run,
175 &batch_cleanup,
176 &batch_traits, NULL);
177}
178
179
180bool
181GNUNET_TESTING_cmd_batch_next_ (void *cls)
182{
183 struct BatchState *bs = cls;
184
185 if (NULL == bs->batch[bs->batch_ip].run)
186 return false;
187 bs->batch[bs->batch_ip].finish_time
188 = GNUNET_TIME_absolute_get ();
189 bs->batch_ip++;
190 return true;
191}
192
193
194bool
195GNUNET_TESTING_cmd_is_batch_ (const struct GNUNET_TESTING_Command *cmd)
196{
197 return cmd->run == &batch_run;
198}
199
200
201struct GNUNET_TESTING_Command *
202GNUNET_TESTING_cmd_batch_get_current_ (const struct GNUNET_TESTING_Command *cmd)
203{
204 struct BatchState *bs = cmd->cls;
205
206 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
207 return &bs->batch[bs->batch_ip];
208}
209
210
211void
212GNUNET_TESTING_cmd_batch_set_current_ (const struct GNUNET_TESTING_Command *cmd,
213 unsigned int new_ip)
214{
215 struct BatchState *bs = cmd->cls;
216
217 /* sanity checks */
218 GNUNET_assert (GNUNET_TESTING_cmd_is_batch_ (cmd));
219 for (unsigned int i = 0; i < new_ip; i++)
220 GNUNET_assert (NULL != bs->batch[i].label);
221 /* actual logic */
222 bs->batch_ip = new_ip;
223}