diff options
Diffstat (limited to 'src/testing/testing_api_cmd_finish.c')
-rw-r--r-- | src/testing/testing_api_cmd_finish.c | 112 |
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 | */ |
80 | static void | 69 | static void |
81 | done_finish (void *cls) | 70 | done_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 | */ |
97 | static void | 86 | static void |
98 | timeout_finish (void *cls) | 87 | timeout_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 | */ |
116 | static void | 104 | static void |
117 | run_finish_on_ref (void *cls, | 105 | run_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 | */ |
169 | static enum GNUNET_GenericReturnValue | 152 | static void |
170 | finish_finish_on_ref (void *cls, | 153 | cleanup_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 | */ | ||
209 | const struct GNUNET_TESTING_Command | 166 | const struct GNUNET_TESTING_Command |
210 | GNUNET_TESTING_cmd_finish (const char *finish_label, | 167 | GNUNET_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 | } |