aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_api_cmd_finish.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testing/testing_api_cmd_finish.c')
-rw-r--r--src/testing/testing_api_cmd_finish.c112
1 files changed, 35 insertions, 77 deletions
diff --git a/src/testing/testing_api_cmd_finish.c b/src/testing/testing_api_cmd_finish.c
index 2bcefd803..3ac0871a5 100644
--- a/src/testing/testing_api_cmd_finish.c
+++ b/src/testing/testing_api_cmd_finish.c
@@ -48,34 +48,23 @@ struct FinishState
48 struct GNUNET_SCHEDULER_Task *finish_task; 48 struct GNUNET_SCHEDULER_Task *finish_task;
49 49
50 /** 50 /**
51 * Interpreter we are part of.
52 */
53 struct GNUNET_TESTING_Interpreter *is;
54
55 /**
56 * Function to call when done. 51 * Function to call when done.
57 */ 52 */
58 GNUNET_SCHEDULER_TaskCallback cont; 53 struct GNUNET_TESTING_AsyncContext ac;
59
60 /**
61 * Closure for @e cont.
62 */
63 void *cont_cls;
64 54
65 /** 55 /**
66 * How long to wait until finish fails hard? 56 * How long to wait until finish fails hard?
67 */ 57 */
68 struct GNUNET_TIME_Relative timeout; 58 struct GNUNET_TIME_Relative timeout;
69 59
70 /**
71 * Set to #GNUNET_OK if the @a async_label command finished on time
72 */
73 enum GNUNET_GenericReturnValue finished;
74
75}; 60};
76 61
77 62
78/** 63/**
64 * Function called when the command we are waiting on
65 * is finished. Hence we are finished, too.
66 *
67 * @param cls a `struct FinishState` being notified
79 */ 68 */
80static void 69static void
81done_finish (void *cls) 70done_finish (void *cls)
@@ -84,15 +73,15 @@ done_finish (void *cls)
84 73
85 GNUNET_SCHEDULER_cancel (finish_state->finish_task); 74 GNUNET_SCHEDULER_cancel (finish_state->finish_task);
86 finish_state->finish_task = NULL; 75 finish_state->finish_task = NULL;
87 finish_state->finished = GNUNET_YES; 76 GNUNET_TESTING_async_finish (&finish_state->ac);
88 if (NULL != finish_state->cont)
89 {
90 finish_state->cont (finish_state->cont_cls);
91 }
92} 77}
93 78
94 79
95/** 80/**
81 * Function triggered if the command we are waiting
82 * for did not complete on time.
83 *
84 * @param cls our `struct FinishState`
96 */ 85 */
97static void 86static void
98timeout_finish (void *cls) 87timeout_finish (void *cls)
@@ -103,8 +92,7 @@ timeout_finish (void *cls)
103 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 92 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
104 "Timeout waiting for command `%s' to finish\n", 93 "Timeout waiting for command `%s' to finish\n",
105 finish_state->async_label); 94 finish_state->async_label);
106 finish_state->finished = GNUNET_SYSERR; 95 GNUNET_TESTING_async_fail (&finish_state->ac);
107 GNUNET_TESTING_interpreter_fail (finish_state->is);
108} 96}
109 97
110 98
@@ -114,13 +102,13 @@ timeout_finish (void *cls)
114 * 102 *
115 */ 103 */
116static void 104static void
117run_finish_on_ref (void *cls, 105run_finish (void *cls,
118 struct GNUNET_TESTING_Interpreter *is) 106 struct GNUNET_TESTING_Interpreter *is)
119{ 107{
120 struct FinishState *finish_state = cls; 108 struct FinishState *finish_state = cls;
121 const struct GNUNET_TESTING_Command *async_cmd; 109 const struct GNUNET_TESTING_Command *async_cmd;
110 struct GNUNET_TESTING_AsyncContext *aac;
122 111
123 finish_state->is = is;
124 async_cmd 112 async_cmd
125 = GNUNET_TESTING_interpreter_lookup_command (is, 113 = GNUNET_TESTING_interpreter_lookup_command (is,
126 finish_state->async_label); 114 finish_state->async_label);
@@ -132,7 +120,7 @@ run_finish_on_ref (void *cls,
132 GNUNET_TESTING_interpreter_fail (is); 120 GNUNET_TESTING_interpreter_fail (is);
133 return; 121 return;
134 } 122 }
135 if ( (NULL == async_cmd->finish) || 123 if ( (NULL == (aac = async_cmd->ac)) ||
136 (! async_cmd->asynchronous_finish) ) 124 (! async_cmd->asynchronous_finish) )
137 { 125 {
138 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -141,71 +129,40 @@ run_finish_on_ref (void *cls,
141 GNUNET_TESTING_interpreter_fail (is); 129 GNUNET_TESTING_interpreter_fail (is);
142 return; 130 return;
143 } 131 }
132 if (GNUNET_NO != aac->finished)
133 {
134 /* Command is already finished, so are we! */
135 GNUNET_TESTING_async_finish (&finish_state->ac);
136 return;
137 }
144 finish_state->finish_task 138 finish_state->finish_task
145 = GNUNET_SCHEDULER_add_delayed (finish_state->timeout, 139 = GNUNET_SCHEDULER_add_delayed (finish_state->timeout,
146 &timeout_finish, 140 &timeout_finish,
147 finish_state); 141 finish_state);
148 async_cmd->finish (async_cmd->cls, 142 aac->cont = &done_finish;
149 &done_finish, 143 aac->cont_cls = finish_state;
150 finish_state);
151} 144}
152 145
153 146
154/** 147/**
155 * Wait for any asynchronous execution of @e run to conclude, 148 * Cleanup state of a finish command.
156 * then call finish_cont. Finish may only be called once per command.
157 * 149 *
158 * This member may be NULL if this command is a synchronous command, 150 * @param cls a `struct FinishState` to clean up
159 * and also should be set to NULL once the command has finished.
160 *
161 * @param cls closure
162 * @param cont function to call upon completion, can be NULL
163 * @param cont_cls closure for @a cont
164 * @return
165 * #GNUNET_NO if the command is still running and @a cont will be called later
166 * #GNUNET_OK if the command completed successfully and @a cont was called
167 * #GNUNET_SYSERR if the operation @a cont was NOT called
168 */ 151 */
169static enum GNUNET_GenericReturnValue 152static void
170finish_finish_on_ref (void *cls, 153cleanup_finish (void *cls)
171 GNUNET_SCHEDULER_TaskCallback cont,
172 void *cont_cls)
173{ 154{
174 struct FinishState *finish_state = cls; 155 struct FinishState *finish_state = cls;
175 156
176 switch (finish_state->finished) 157 if (NULL != finish_state->finish_task)
177 { 158 {
178 case GNUNET_OK: 159 GNUNET_SCHEDULER_cancel (finish_state->finish_task);
179 cont (cont_cls); 160 finish_state->finish_task = NULL;
180 break;
181 case GNUNET_SYSERR:
182 GNUNET_break (0);
183 break;
184 case GNUNET_NO:
185 if (NULL != finish_state->cont)
186 {
187 GNUNET_break (0);
188 return GNUNET_SYSERR;
189 }
190 finish_state->cont = cont;
191 finish_state->cont_cls = cont_cls;
192 break;
193 } 161 }
194 return finish_state->finished; 162 GNUNET_free (finish_state);
195} 163}
196 164
197 165
198/**
199 * Create (synchronous) command that waits for another command to finish.
200 * If @a cmd_ref did not finish after @a timeout, this command will fail
201 * the test case.
202 *
203 * @param finish_label label for this command
204 * @param cmd_ref reference to a previous command which we should
205 * wait for (call `finish()` on)
206 * @param timeout how long to wait at most for @a cmd_ref to finish
207 * @return a finish-command.
208 */
209const struct GNUNET_TESTING_Command 166const struct GNUNET_TESTING_Command
210GNUNET_TESTING_cmd_finish (const char *finish_label, 167GNUNET_TESTING_cmd_finish (const char *finish_label,
211 const char *cmd_ref, 168 const char *cmd_ref,
@@ -220,8 +177,9 @@ GNUNET_TESTING_cmd_finish (const char *finish_label,
220 struct GNUNET_TESTING_Command cmd = { 177 struct GNUNET_TESTING_Command cmd = {
221 .cls = finish_state, 178 .cls = finish_state,
222 .label = finish_label, 179 .label = finish_label,
223 .run = &run_finish_on_ref, 180 .run = &run_finish,
224 .finish = &finish_finish_on_ref 181 .ac = &finish_state->ac,
182 .cleanup = &cleanup_finish
225 }; 183 };
226 184
227 return cmd; 185 return cmd;
@@ -234,7 +192,7 @@ GNUNET_TESTING_cmd_make_unblocking (struct GNUNET_TESTING_Command cmd)
234{ 192{
235 /* do not permit this function to be used on 193 /* do not permit this function to be used on
236 a finish command! */ 194 a finish command! */
237 GNUNET_assert (cmd.run != &run_finish_on_ref); 195 GNUNET_assert (cmd.run != &run_finish);
238 cmd.asynchronous_finish = true; 196 cmd.asynchronous_finish = true;
239 return cmd; 197 return cmd;
240} 198}