aboutsummaryrefslogtreecommitdiff
path: root/src/transport/transport-testing-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/transport/transport-testing-main.c')
-rw-r--r--src/transport/transport-testing-main.c435
1 files changed, 434 insertions, 1 deletions
diff --git a/src/transport/transport-testing-main.c b/src/transport/transport-testing-main.c
index 9cda749fe..8dfd51074 100644
--- a/src/transport/transport-testing-main.c
+++ b/src/transport/transport-testing-main.c
@@ -26,6 +26,401 @@
26 26
27 27
28/** 28/**
29 * Closure for #connect_cb.
30 */
31struct GNUNET_TRANSPORT_TESTING_ConnectRequestList
32{
33 /**
34 * Stored in a DLL.
35 */
36 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *next;
37
38 /**
39 * Stored in a DLL.
40 */
41 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *prev;
42
43 /**
44 * Overall context we are in.
45 */
46 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
47
48 /**
49 * Connect request this is about.
50 */
51 struct GNUNET_TRANSPORT_TESTING_ConnectRequest *cr;
52
53 /**
54 * Peer being connected.
55 */
56 struct GNUNET_TRANSPORT_TESTING_PeerContext *p1;
57
58 /**
59 * Peer being connected.
60 */
61 struct GNUNET_TRANSPORT_TESTING_PeerContext *p2;
62
63};
64
65
66/**
67 * Shutdown function for the test. Stops all peers.
68 *
69 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
70 */
71static void
72do_shutdown (void *cls)
73{
74 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
75 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
76
77 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78 "Testcase shutting down\n");
79 if (NULL != ccc->shutdown_task)
80 ccc->shutdown_task (ccc->shutdown_task_cls);
81 if (NULL != ccc->timeout_task)
82 {
83 GNUNET_SCHEDULER_cancel (ccc->timeout_task);
84 ccc->timeout_task = NULL;
85 }
86 while (NULL != (crl = ccc->crl_head))
87 {
88 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
89 ccc->crl_tail,
90 crl);
91 GNUNET_TRANSPORT_TESTING_connect_peers_cancel (crl->cr);
92 GNUNET_free (crl);
93 }
94 for (unsigned int i=0;i<ccc->num_peers;i++)
95 {
96 GNUNET_TRANSPORT_TESTING_stop_peer (ccc->p[i]);
97 ccc->p[i] = NULL;
98 }
99}
100
101
102/**
103 * Testcase hit timeout, shut it down with error.
104 *
105 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
106 */
107static void
108do_timeout (void *cls)
109{
110 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
111
112 ccc->timeout_task = NULL;
113 GNUNET_break (0); /* signal timeout */
114 ccc->global_ret = GNUNET_SYSERR;
115 GNUNET_SCHEDULER_shutdown ();
116}
117
118
119/**
120 * Internal data structure. Closure for
121 * #connect_cb, #disconnect_cb, #my_nc and #start_cb.
122 * Allows us to identify which peer this is about.
123 */
124struct GNUNET_TRANSPORT_TESTING_InternalPeerContext
125{
126 /**
127 * Overall context of the callback.
128 */
129 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
130
131 /**
132 * Offset of the peer this is about.
133 */
134 unsigned int off;
135};
136
137
138/**
139 * Function called when we connected two peers.
140 * Once we have gotten to the clique, launch
141 * test-specific logic.
142 *
143 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *`
144 */
145static void
146connect_cb (void *cls)
147{
148 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl = cls;
149 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = crl->ccc;
150
151 GNUNET_CONTAINER_DLL_remove (ccc->crl_head,
152 ccc->crl_tail,
153 crl);
154 {
155 char *p1_c = GNUNET_strdup (GNUNET_i2s (&crl->p1->id));
156
157 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
158 "Peers connected: %u (%s) <-> %u (%s)\n",
159 crl->p1->no,
160 p1_c,
161 crl->p2->no,
162 GNUNET_i2s (&crl->p2->id));
163 GNUNET_free (p1_c);
164 GNUNET_free (crl);
165 }
166 if (NULL == ccc->crl_head)
167 {
168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
169 "All connections UP, launching custom test logic.\n");
170 GNUNET_SCHEDULER_add_now (ccc->connect_continuation,
171 ccc->connect_continuation_cls);
172 }
173}
174
175
176/**
177 * Find peer by peer ID.
178 *
179 * @param ccc context to search
180 * @param peer peer to look for
181 * @return NULL if @a peer was not found
182 */
183struct GNUNET_TRANSPORT_TESTING_PeerContext *
184GNUNET_TRANSPORT_TESTING_find_peer (struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc,
185 const struct GNUNET_PeerIdentity *peer)
186{
187 for (unsigned int i=0;i<ccc->num_peers;i++)
188 if ( (NULL != ccc->p[i]) &&
189 (0 == memcmp (peer,
190 &ccc->p[i]->id,
191 sizeof (*peer))) )
192 return ccc->p[i];
193 return NULL;
194}
195
196
197/**
198 * Wrapper around peers connecting. Calls client's nc function.
199 *
200 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
201 * @param peer peer we got connected to
202 */
203static void
204my_nc (void *cls,
205 const struct GNUNET_PeerIdentity *peer)
206{
207 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
208 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
209
210 if (NULL != ccc->nc)
211 ccc->nc (ccc->cls,
212 ccc->p[ipi->off],
213 peer);
214}
215
216
217
218/**
219 * Wrapper around peers disconnecting. Calls client's nd function.
220 *
221 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
222 * @param peer peer we got disconnected from
223 */
224static void
225my_nd (void *cls,
226 const struct GNUNET_PeerIdentity *peer)
227{
228 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
229 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
230
231 if (NULL != ccc->nd)
232 ccc->nd (ccc->cls,
233 ccc->p[ipi->off],
234 peer);
235}
236
237
238/**
239 * Wrapper around receiving data. Calls client's rec function.
240 *
241 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
242 * @param peer peer we got a message from
243 * @param message message we received
244 */
245static void
246my_rec (void *cls,
247 const struct GNUNET_PeerIdentity *peer,
248 const struct GNUNET_MessageHeader *message)
249{
250 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
251 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
252
253 if (NULL != ccc->rec)
254 ccc->rec (ccc->cls,
255 ccc->p[ipi->off],
256 peer,
257 message);
258}
259
260
261/**
262 * Function called once we have successfully launched a peer.
263 * Once all peers have been launched, we connect all of them
264 * in a clique.
265 *
266 * @param p peer that was launched (redundant, kill ASAP)
267 * @param cls our `struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *`
268 */
269static void
270start_cb (struct GNUNET_TRANSPORT_TESTING_PeerContext *p,
271 void *cls)
272{
273 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext *ipi = cls;
274 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = ipi->ccc;
275
276 ccc->started++;
277 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
278 "Peer %u (`%s') started\n",
279 p->no,
280 GNUNET_i2s (&p->id));
281 if (ccc->started != ccc->num_peers)
282 return;
283
284 for (unsigned int i=0;i<ccc->num_peers;i++)
285 for (unsigned int j=i+1;j<ccc->num_peers;j++)
286 {
287 struct GNUNET_TRANSPORT_TESTING_ConnectRequestList *crl;
288
289 crl = GNUNET_new (struct GNUNET_TRANSPORT_TESTING_ConnectRequestList);
290 GNUNET_CONTAINER_DLL_insert (ccc->crl_head,
291 ccc->crl_tail,
292 crl);
293 crl->ccc = ccc;
294 crl->p1 = ccc->p[i];
295 crl->p2 = ccc->p[j];
296 {
297 char *sender_c = GNUNET_strdup (GNUNET_i2s (&ccc->p[0]->id));
298
299 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
300 "Test tries to connect peer %u (`%s') -> peer %u (`%s')\n",
301 ccc->p[0]->no,
302 sender_c,
303 ccc->p[1]->no,
304 GNUNET_i2s (&ccc->p[1]->id));
305 GNUNET_free (sender_c);
306 }
307 crl->cr = GNUNET_TRANSPORT_TESTING_connect_peers (ccc->p[i],
308 ccc->p[j],
309 &connect_cb,
310 crl);
311 }
312}
313
314
315/**
316 * Function run from #GNUNET_TRANSPORT_TESTING_connect_check
317 * once the scheduler is up. Should launch the peers and
318 * then in the continuations try to connect them.
319 *
320 * @param cls our `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *`
321 * @param args ignored
322 * @param cfgfile ignored
323 * @param cfg configuration
324 */
325static void
326connect_check_run (void *cls,
327 char *const *args,
328 const char *cfgfile,
329 const struct GNUNET_CONFIGURATION_Handle *cfg)
330{
331 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
332 int ok;
333
334 ccc->cfg = cfg;
335 ccc->timeout_task = GNUNET_SCHEDULER_add_delayed (ccc->timeout,
336 &do_timeout,
337 ccc);
338 GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
339 ccc);
340 ok = GNUNET_OK;
341 for (unsigned int i=0;i<ccc->num_peers;i++)
342 {
343 ccc->p[i] = GNUNET_TRANSPORT_TESTING_start_peer (ccc->tth,
344 ccc->cfg_files[i],
345 i + 1,
346 &my_rec,
347 &my_nc,
348 &my_nd,
349 &start_cb,
350 &ccc->ip[i]);
351 if (NULL == ccc->p[i])
352 ok = GNUNET_SYSERR;
353 }
354 if (GNUNET_OK != ok)
355 {
356 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
357 "Fail! Could not start peers!\n");
358 GNUNET_SCHEDULER_shutdown ();
359 }
360}
361
362
363/**
364 * Common implementation of the #GNUNET_TRANSPORT_TESTING_CheckCallback.
365 * Starts and connects the two peers, then invokes the
366 * `connect_continuation` from @a cls. Sets up a timeout to
367 * abort the test, and a shutdown handler to clean up properly
368 * on exit.
369 *
370 * @param cls closure of type `struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext`
371 * @param tth_ initialized testing handle
372 * @param test_plugin_ name of the plugin
373 * @param test_name_ name of the test
374 * @param num_peers number of entries in the @a cfg_file array
375 * @param cfg_files array of names of configuration files for the peers
376 * @return #GNUNET_SYSERR on error
377 */
378int
379GNUNET_TRANSPORT_TESTING_connect_check (void *cls,
380 struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
381 const char *test_plugin_,
382 const char *test_name_,
383 unsigned int num_peers,
384 char *cfg_files[])
385{
386 static struct GNUNET_GETOPT_CommandLineOption options[] = {
387 GNUNET_GETOPT_OPTION_END
388 };
389 struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc = cls;
390 struct GNUNET_TRANSPORT_TESTING_PeerContext *p[num_peers];
391 struct GNUNET_TRANSPORT_TESTING_InternalPeerContext ip[num_peers];
392 char * argv[] = {
393 (char *) test_name_,
394 "-c",
395 (char *) ccc->config_file,
396 NULL
397 };
398
399 ccc->num_peers = num_peers;
400 ccc->cfg_files = cfg_files;
401 ccc->test_plugin = test_plugin_;
402 ccc->test_name = test_name_;
403 ccc->tth = tth_;
404 ccc->global_ret = GNUNET_OK;
405 ccc->p = p;
406 ccc->ip = ip;
407 for (unsigned int i=0;i<num_peers;i++)
408 {
409 ip[i].off = i;
410 ip[i].ccc = ccc;
411 }
412 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
413 argv,
414 test_name_,
415 "nohelp",
416 options,
417 &connect_check_run,
418 ccc);
419 return ccc->global_ret;
420}
421
422
423/**
29 * Setup testcase. Calls @a check with the data the test needs. 424 * Setup testcase. Calls @a check with the data the test needs.
30 * 425 *
31 * @param argv0 binary name (argv[0]) 426 * @param argv0 binary name (argv[0])
@@ -42,7 +437,45 @@ GNUNET_TRANSPORT_TESTING_main_ (const char *argv0,
42 GNUNET_TRANSPORT_TESTING_CheckCallback check, 437 GNUNET_TRANSPORT_TESTING_CheckCallback check,
43 void *check_cls) 438 void *check_cls)
44{ 439{
45 return GNUNET_SYSERR; 440 struct GNUNET_TRANSPORT_TESTING_Handle *tth;
441 char *test_name;
442 char *test_source;
443 char *test_plugin;
444 char *cfg_names[num_peers];
445 int ret;
446
447 ret = GNUNET_OK;
448 test_name = GNUNET_TRANSPORT_TESTING_get_test_name (argv0);
449 GNUNET_log_setup (test_name,
450 "WARNING",
451 NULL);
452 test_source = GNUNET_TRANSPORT_TESTING_get_test_source_name (filename);
453 test_plugin = GNUNET_TRANSPORT_TESTING_get_test_plugin_name (argv0,
454 test_source);
455 for (unsigned int i=0;i<num_peers;i++)
456 cfg_names[i] = GNUNET_TRANSPORT_TESTING_get_config_name (argv0,
457 i+1);
458 tth = GNUNET_TRANSPORT_TESTING_init ();
459 if (NULL == tth)
460 {
461 ret = GNUNET_SYSERR;
462 }
463 else
464 {
465 ret = check (check_cls,
466 tth,
467 test_plugin,
468 test_name,
469 num_peers,
470 cfg_names);
471 GNUNET_TRANSPORT_TESTING_done (tth);
472 }
473 for (unsigned int i=0;i<num_peers;i++)
474 GNUNET_free (cfg_names[i]);
475 GNUNET_free (test_source);
476 GNUNET_free (test_plugin);
477 GNUNET_free (test_name);
478 return ret;
46} 479}
47 480
48/* end of transport-testing-main.c */ 481/* end of transport-testing-main.c */