aboutsummaryrefslogtreecommitdiff
path: root/src/lib/testing/testing_api_cmd_barrier_reached.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/testing/testing_api_cmd_barrier_reached.c')
-rw-r--r--src/lib/testing/testing_api_cmd_barrier_reached.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/lib/testing/testing_api_cmd_barrier_reached.c b/src/lib/testing/testing_api_cmd_barrier_reached.c
new file mode 100644
index 000000000..161240d4d
--- /dev/null
+++ b/src/lib/testing/testing_api_cmd_barrier_reached.c
@@ -0,0 +1,229 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2022 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_barrier_reached.c
23 * @brief Command to signal barrier was reached.
24 * @author t3sserakt
25 */
26#include "platform.h"
27#include "gnunet_testing_lib.h"
28#include "testing_cmds.h"
29#include "gnunet_testing_plugin.h"
30#include "gnunet_testing_barrier.h"
31#include "gnunet_testing_netjail_lib.h"
32#include "testing.h"
33
34/**
35 * Generic logging shortcut
36 */
37#define LOG(kind, ...) GNUNET_log (kind, __VA_ARGS__)
38
39/**
40 * Struct with information for callbacks.
41 *
42 */
43struct BarrierReachedState
44{
45 /**
46 * Callback to write messages to the master loop.
47 *
48 */
49 GNUNET_TESTING_cmd_helper_write_cb write_message;
50
51 /**
52 * Context for our asynchronous completion.
53 */
54 struct GNUNET_TESTING_AsyncContext ac;
55
56 /**
57 * The label of this command.
58 */
59 const char *label;
60
61 /**
62 * The name of the barrier this commands wait (if finishing asynchronous) for or/and reaches.
63 */
64 const char *barrier_name;
65
66 /*
67 * The global numer of the node the cmd runs on.
68 */
69 unsigned int node_number;
70
71 /**
72 * If this command will block.
73 */
74 unsigned int asynchronous_finish;
75
76 /**
77 * Is this cmd running on the master loop.
78 */
79 unsigned int running_on_master;
80};
81
82
83/**
84 * Run the command.
85 *
86 * @param cls closure.
87 * @param is the interpreter state.
88 */
89static void
90barrier_reached_run (void *cls,
91 struct GNUNET_TESTING_Interpreter *is)
92{
93 struct BarrierReachedState *brs = cls;
94 struct GNUNET_TESTING_Barrier *barrier;
95 struct GNUNET_TESTING_Command *cmd =
96 GNUNET_TESTING_interpreter_get_current_command (is);
97 struct CommandListEntry *cle;
98 size_t msg_length;
99 struct GNUNET_TESTING_CommandBarrierReached *msg;
100 size_t name_len;
101
102 barrier = TST_interpreter_get_barrier (is, brs->barrier_name);
103 if (NULL == barrier)
104 {
105 barrier = GNUNET_new (struct GNUNET_TESTING_Barrier);
106 barrier->name = brs->barrier_name;
107 TST_interpreter_add_barrier (is, barrier);
108 LOG (GNUNET_ERROR_TYPE_DEBUG,
109 "barrier %s added locally\n",
110 brs->barrier_name);
111 }
112 barrier->reached++;
113 if (GNUNET_TESTING_barrier_crossable (barrier))
114 {
115 GNUNET_assert (NULL != cmd);
116 cmd->asynchronous_finish = GNUNET_YES;
117 TST_interpreter_finish_attached_cmds (is, barrier->name);
118 }
119 else if (GNUNET_NO == brs->asynchronous_finish)
120 {
121 cle = GNUNET_new (struct CommandListEntry);
122 cle->command = cmd;
123 GNUNET_CONTAINER_DLL_insert (barrier->cmds_head,
124 barrier->cmds_tail,
125 cle);
126 LOG (GNUNET_ERROR_TYPE_DEBUG,
127 "added cle for %p %s\n",
128 barrier,
129 barrier->name);
130 }
131
132 if (GNUNET_NO == brs->running_on_master)
133 {
134 char *terminator = "\0";
135
136 name_len = strlen (barrier->name);
137 msg_length = sizeof(struct GNUNET_TESTING_CommandBarrierReached)
138 + name_len + 1;
139 msg = GNUNET_malloc (msg_length);
140 msg->header.size = htons ((uint16_t) msg_length);
141 msg->header.type = htons (GNUNET_MESSAGE_TYPE_CMDS_HELPER_BARRIER_REACHED);
142 msg->node_number = brs->node_number;
143 memcpy (&msg[1], barrier->name, name_len + 1);
144 memcpy (&msg[name_len + 1],terminator,1);
145 brs->write_message ((struct GNUNET_MessageHeader *) msg, msg_length);
146 }
147}
148
149
150/**
151 * Cleanup the state from a "barrier reached" CMD, and possibly
152 * cancel a pending operation thereof.
153 *
154 * @param cls closure.
155 */
156static void
157barrier_reached_cleanup (void *cls)
158{
159 struct BarrierReachedState *brs = cls;
160
161 GNUNET_free (brs);
162}
163
164
165/**
166 * Offer internal data from a "batch" CMD, to other commands.
167 *
168 * @param cls closure.
169 * @param[out] ret result.
170 * @param trait name of the trait.
171 * @param index index number of the object to offer.
172 * @return #GNUNET_OK on success.
173 */
174static enum GNUNET_GenericReturnValue
175barrier_reached_traits (void *cls,
176 const void **ret,
177 const char *trait,
178 unsigned int index)
179{
180 struct BarrierReachedState *brs = cls;
181 struct GNUNET_TESTING_AsyncContext *ac = &brs->ac;
182
183 struct GNUNET_TESTING_Trait traits[] = {
184 GNUNET_TESTING_make_trait_async_context (ac),
185 GNUNET_TESTING_trait_end ()
186 };
187
188 return GNUNET_TESTING_get_trait (traits,
189 ret,
190 trait,
191 index);
192}
193
194
195/**
196 * Create command.
197 *
198 * @param label name for command.
199 * @param barrier_label The name of the barrier we wait for (if finishing asynchronous) and which will be reached.
200 * @param asynchronous_finish If GNUNET_YES this command will not block.
201 * @param node_number The global numer of the node the cmd runs on.
202 * @param running_on_master Is this cmd running on the master loop.
203 * @param write_message Callback to write messages to the master loop.
204 * @return command.
205 */
206struct GNUNET_TESTING_Command
207GNUNET_TESTING_cmd_barrier_reached (
208 const char *label,
209 const char *barrier_label,
210 unsigned int asynchronous_finish,
211 unsigned int node_number,
212 unsigned int running_on_master,
213 GNUNET_TESTING_cmd_helper_write_cb write_message)
214{
215 struct BarrierReachedState *brs;
216
217 brs = GNUNET_new (struct BarrierReachedState);
218 brs->label = label;
219 brs->barrier_name = barrier_label;
220 brs->asynchronous_finish = asynchronous_finish;
221 brs->node_number = node_number;
222 brs->running_on_master = running_on_master;
223 brs->write_message = write_message;
224 return GNUNET_TESTING_command_new (brs, label,
225 &barrier_reached_run,
226 &barrier_reached_cleanup,
227 &barrier_reached_traits,
228 &brs->ac);
229}