diff options
Diffstat (limited to 'src/vectorproduct/test_vectorproduct_api_regression.c')
-rw-r--r-- | src/vectorproduct/test_vectorproduct_api_regression.c | 852 |
1 files changed, 852 insertions, 0 deletions
diff --git a/src/vectorproduct/test_vectorproduct_api_regression.c b/src/vectorproduct/test_vectorproduct_api_regression.c new file mode 100644 index 000000000..2bc0adec6 --- /dev/null +++ b/src/vectorproduct/test_vectorproduct_api_regression.c | |||
@@ -0,0 +1,852 @@ | |||
1 | |||
2 | /* | ||
3 | This file is part of GNUnet. | ||
4 | (C) 2013 Christian Grothoff (and other contributing authors) | ||
5 | |||
6 | GNUnet is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License as published | ||
8 | by the Free Software Foundation; either version 3, or (at your | ||
9 | option) any later version. | ||
10 | |||
11 | GNUnet is distributed in the hope that it will be useful, but | ||
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU General Public License | ||
17 | along with GNUnet; see the file COPYING. If not, write to the | ||
18 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
19 | Boston, MA 02111-1307, USA. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file vectorproduct/test_vectorproduct_api_regression.c | ||
24 | * @brief VectorProduct API regression test | ||
25 | * @author Gaurav Kukreja | ||
26 | * @author Christian Fuchs | ||
27 | */ | ||
28 | |||
29 | /** | ||
30 | * AIM of the regression test | ||
31 | * | ||
32 | * This test tries to check whether the service can handle abrupt client disconnect. | ||
33 | * | ||
34 | * 1. We create a responder peer, and ask the service to prepare_response. After this, | ||
35 | * we disconnect responder peer from service. | ||
36 | * | ||
37 | * 2. Then we create a requester peer, and ask service to request another peer. We | ||
38 | * should check that the service on responder peer is still active and receives | ||
39 | * request from the requester. We then disconnect requester peer from service. Both | ||
40 | * the requester and responder service should handle this cleanly. | ||
41 | */ | ||
42 | |||
43 | #include <string.h> | ||
44 | |||
45 | #include <inttypes.h> | ||
46 | #include "platform.h" | ||
47 | #include "gnunet_util_lib.h" | ||
48 | #include "gnunet_testbed_service.h" | ||
49 | #include "gnunet_common.h" | ||
50 | #include "gnunet_vectorproduct_service.h" | ||
51 | #include "gnunet_protocols.h" | ||
52 | |||
53 | #define LOG(kind,...) GNUNET_log_from (kind, "test-vectorproduct-api-regression",__VA_ARGS__) | ||
54 | #define NUM_PEERS 2 | ||
55 | |||
56 | /** | ||
57 | * Structure for holding peer's sockets and IO Handles | ||
58 | */ | ||
59 | struct PeerData | ||
60 | { | ||
61 | /** | ||
62 | * Handle to testbed peer | ||
63 | */ | ||
64 | struct GNUNET_TESTBED_Peer *peer; | ||
65 | |||
66 | /** | ||
67 | * The service connect operation to stream | ||
68 | */ | ||
69 | struct GNUNET_TESTBED_Operation *op; | ||
70 | |||
71 | /** | ||
72 | * Our Peer id | ||
73 | */ | ||
74 | struct GNUNET_PeerIdentity our_id; | ||
75 | |||
76 | /** | ||
77 | * Pointer to Vector Product Handle | ||
78 | */ | ||
79 | struct GNUNET_VECTORPRODUCT_Handle *vh; | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * Different states in test setup | ||
84 | */ | ||
85 | enum SetupState | ||
86 | { | ||
87 | /** | ||
88 | * Get the identity of peer 1 | ||
89 | */ | ||
90 | PEER1_GET_IDENTITY, | ||
91 | |||
92 | /** | ||
93 | * Get the identity of peer 2 | ||
94 | */ | ||
95 | PEER2_GET_IDENTITY, | ||
96 | |||
97 | /** | ||
98 | * Connect to stream service of peer 1 | ||
99 | */ | ||
100 | PEER1_VECTORPRODUCT_CONNECT, | ||
101 | |||
102 | /** | ||
103 | * Connect to stream service of peer 2 | ||
104 | */ | ||
105 | PEER2_VECTORPRODUCT_CONNECT | ||
106 | |||
107 | }; | ||
108 | |||
109 | /****************************************************************************** | ||
110 | *** Global Variables ***************************** | ||
111 | ******************************************************************************/ | ||
112 | |||
113 | /** | ||
114 | * Maximum allowed message-ids we can check in one go (with one GNUNET_message) | ||
115 | */ | ||
116 | static unsigned int max_mids; | ||
117 | |||
118 | /** | ||
119 | * Session Key used by both the test peers | ||
120 | */ | ||
121 | char input_key[103] = "helloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhelloworldhe"; | ||
122 | |||
123 | /** | ||
124 | * Input elements for peer1 | ||
125 | */ | ||
126 | //char input_elements_peer1[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11"; | ||
127 | char input_elements_peer1[] = "11,11,11"; | ||
128 | |||
129 | /** | ||
130 | * Input Mask for peer 1 | ||
131 | */ | ||
132 | //char input_mask_peer1[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; | ||
133 | char input_mask_peer1[] = "1,1,1"; | ||
134 | |||
135 | /** | ||
136 | * the array of converted message IDs to send to our service | ||
137 | */ | ||
138 | static int32_t * elements_peer1 = NULL; | ||
139 | |||
140 | /** | ||
141 | * Input elements for peer2 | ||
142 | */ | ||
143 | //char input_elements_peer2[] = "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11"; | ||
144 | char input_elements_peer2[] = "11,11,11"; | ||
145 | /** | ||
146 | * Input Mask for peer 2 | ||
147 | */ | ||
148 | //char input_mask_peer2[] = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; | ||
149 | char input_mask_peer2[] = "1,1,1"; | ||
150 | /** | ||
151 | * the array of converted message IDs to send to our service | ||
152 | */ | ||
153 | static int32_t * elements_peer2 = NULL; | ||
154 | |||
155 | /** | ||
156 | * the array of converted message IDs to send to our service | ||
157 | */ | ||
158 | static unsigned char * mask_peer2 = NULL; | ||
159 | |||
160 | /** | ||
161 | * Data context for peer 1 | ||
162 | */ | ||
163 | static struct PeerData peer1; | ||
164 | |||
165 | /** | ||
166 | * Data context for peer 2 | ||
167 | */ | ||
168 | static struct PeerData peer2; | ||
169 | |||
170 | /** | ||
171 | * Various states during test setup | ||
172 | */ | ||
173 | static enum SetupState setup_state; | ||
174 | |||
175 | /** | ||
176 | * Testbed operation handle | ||
177 | */ | ||
178 | static struct GNUNET_TESTBED_Operation *op; | ||
179 | |||
180 | /** | ||
181 | * Return value of the test. | ||
182 | */ | ||
183 | static int ok; | ||
184 | |||
185 | /** | ||
186 | * Abort Task for timeout | ||
187 | */ | ||
188 | static GNUNET_SCHEDULER_TaskIdentifier abort_task; | ||
189 | /****************************************************************************** | ||
190 | *** Static Functions ***************************** | ||
191 | ******************************************************************************/ | ||
192 | |||
193 | /** | ||
194 | * Helper function to shutdown a test peer | ||
195 | * | ||
196 | * @param cls void* to struct PeerData of the peer to be disconnected | ||
197 | * @param tc Task Context | ||
198 | */ | ||
199 | static void | ||
200 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
201 | |||
202 | |||
203 | /** | ||
204 | * Helper function to connect a test peer | ||
205 | * | ||
206 | * @param cls void* to struct PeerData of the peer to be connected | ||
207 | * @param tc Task Context | ||
208 | */ | ||
209 | static void | ||
210 | connect_peer (void *cls, | ||
211 | const struct GNUNET_SCHEDULER_TaskContext * tc); | ||
212 | |||
213 | |||
214 | /** | ||
215 | * Close sockets and stop testing deamons nicely | ||
216 | */ | ||
217 | static void | ||
218 | do_close (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
219 | { | ||
220 | |||
221 | if (peer1.op != NULL) | ||
222 | do_shutdown (&peer1, NULL); | ||
223 | |||
224 | if (peer2.op != NULL) | ||
225 | do_shutdown (&peer2, NULL); | ||
226 | |||
227 | if (GNUNET_SCHEDULER_NO_TASK != abort_task) | ||
228 | GNUNET_SCHEDULER_cancel (abort_task); | ||
229 | |||
230 | GNUNET_SCHEDULER_shutdown (); /* For shutting down testbed */ | ||
231 | } | ||
232 | |||
233 | |||
234 | /** | ||
235 | * Helper function to shutdown a test peer | ||
236 | * | ||
237 | * @param cls void* to struct PeerData of the peer to be disconnected | ||
238 | * @param tc Task Context | ||
239 | */ | ||
240 | static void | ||
241 | do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
242 | { | ||
243 | static int shutdown; | ||
244 | shutdown++; | ||
245 | struct PeerData* peer = (struct PeerData*) cls; | ||
246 | |||
247 | if (peer == &peer1) | ||
248 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting Peer1\n\n"); | ||
249 | else if (peer == &peer2) | ||
250 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting Peer2\n\n"); | ||
251 | |||
252 | // peer->op contains handle to the TESTBED_connect_service operation | ||
253 | // calling operation done, leads to call to vectorproduct_da | ||
254 | if (peer->op != NULL) | ||
255 | { | ||
256 | GNUNET_TESTBED_operation_done (peer->op); | ||
257 | peer->op = NULL; | ||
258 | } | ||
259 | |||
260 | if (shutdown >= 2) | ||
261 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10), &do_close, NULL); | ||
262 | } | ||
263 | |||
264 | |||
265 | /** | ||
266 | * Something went wrong and timed out. Kill everything and set error flag | ||
267 | */ | ||
268 | static void | ||
269 | do_abort (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
270 | { | ||
271 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: ABORT due to Timeout\n"); | ||
272 | ok = GNUNET_SYSERR; | ||
273 | abort_task = 0; | ||
274 | do_close (cls, tc); | ||
275 | } | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Controller event callback | ||
280 | * | ||
281 | * @param cls NULL | ||
282 | * @param event the controller event | ||
283 | */ | ||
284 | static void | ||
285 | controller_event_cb (void *cls, | ||
286 | const struct GNUNET_TESTBED_EventInformation *event) | ||
287 | { | ||
288 | switch (event->type) | ||
289 | { | ||
290 | case GNUNET_TESTBED_ET_OPERATION_FINISHED: | ||
291 | switch (setup_state) | ||
292 | { | ||
293 | case PEER1_VECTORPRODUCT_CONNECT: | ||
294 | case PEER2_VECTORPRODUCT_CONNECT: | ||
295 | GNUNET_assert (NULL == event->details.operation_finished.emsg); | ||
296 | break; | ||
297 | default: | ||
298 | GNUNET_assert (0); | ||
299 | } | ||
300 | break; | ||
301 | default: | ||
302 | GNUNET_assert (0); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | |||
307 | /** | ||
308 | * Callback function called for the responder peer i.e. peer1 | ||
309 | * | ||
310 | * @param cls | ||
311 | * @param key Session key | ||
312 | * @param status Status of the message | ||
313 | */ | ||
314 | static void | ||
315 | responder_callback (void *cls, | ||
316 | const struct GNUNET_HashCode * key, | ||
317 | enum GNUNET_VECTORPRODUCT_ResponseStatus status) | ||
318 | { | ||
319 | if (status == GNUNET_VECTORPRODUCT_Status_Failure) | ||
320 | { | ||
321 | LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status failure\n"); | ||
322 | ok = -1; | ||
323 | } | ||
324 | else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse) | ||
325 | { | ||
326 | LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received status invalid response\n"); | ||
327 | ok = -1; | ||
328 | } | ||
329 | else if (GNUNET_VECTORPRODUCT_Status_Timeout == status) | ||
330 | { | ||
331 | LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received timeout occured\n"); | ||
332 | ok = -1; | ||
333 | } | ||
334 | else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status) | ||
335 | { | ||
336 | LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client received service disconnected!!\n"); | ||
337 | ok = 1; | ||
338 | } | ||
339 | else if (GNUNET_VECTORPRODUCT_Status_Success == status) | ||
340 | { | ||
341 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Responder Client expected response received!\n"); | ||
342 | ok = -1; | ||
343 | } | ||
344 | else | ||
345 | { | ||
346 | LOG (GNUNET_ERROR_TYPE_WARNING, "Responder Client status = %d!\n", (int) status); | ||
347 | ok = -1; | ||
348 | } | ||
349 | |||
350 | // Not shutting down this time, only for this regression test. We have shutdown explicitly earlier. | ||
351 | // Shutting down again is causing problems. | ||
352 | |||
353 | // if(peer1.vh != NULL) | ||
354 | // { | ||
355 | // GNUNET_SCHEDULER_add_now(&do_shutdown, &peer1); | ||
356 | // } | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | |||
361 | /** | ||
362 | * Callback function called for the requester peer i.e. peer2 | ||
363 | * | ||
364 | * @param cls | ||
365 | * @param key Session key | ||
366 | * @param status Status of the message | ||
367 | */ | ||
368 | static void | ||
369 | requester_callback (void *cls, | ||
370 | const struct GNUNET_HashCode * key, | ||
371 | const struct GNUNET_PeerIdentity * peer, | ||
372 | enum GNUNET_VECTORPRODUCT_ResponseStatus status, | ||
373 | const struct GNUNET_VECTORPRODUCT_client_response *msg) | ||
374 | { | ||
375 | uint32_t product_len; | ||
376 | |||
377 | if (status == GNUNET_VECTORPRODUCT_Status_Failure) | ||
378 | { | ||
379 | LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status failure\n"); | ||
380 | ok = -1; | ||
381 | } | ||
382 | else if (status == GNUNET_VECTORPRODUCT_Status_InvalidResponse) | ||
383 | { | ||
384 | LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client received status invalid response\n"); | ||
385 | ok = -1; | ||
386 | } | ||
387 | else if (GNUNET_VECTORPRODUCT_Status_Timeout == status) | ||
388 | { | ||
389 | LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client timeout occured\n"); | ||
390 | ok = -1; | ||
391 | } | ||
392 | else if (GNUNET_VECTORPRODUCT_Status_ServiceDisconnected == status) | ||
393 | { | ||
394 | LOG (GNUNET_ERROR_TYPE_WARNING, "Requester Client service disconnected!!\n"); | ||
395 | ok = 1; | ||
396 | } | ||
397 | else if (GNUNET_VECTORPRODUCT_Status_Success != status) | ||
398 | { | ||
399 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Requester Client Status = %d\n", (int) status); | ||
400 | ok = -1; | ||
401 | } | ||
402 | else if (GNUNET_VECTORPRODUCT_Status_Success == status) | ||
403 | { | ||
404 | product_len = ntohl (msg->product_length); | ||
405 | |||
406 | if (0 < product_len) | ||
407 | { | ||
408 | gcry_mpi_t result; | ||
409 | gcry_error_t ret = 0; | ||
410 | size_t read = 0; | ||
411 | |||
412 | ret = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, (void *) &msg[1], product_len, &read); | ||
413 | |||
414 | if (0 != ret) | ||
415 | { | ||
416 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Could not convert to mpi to value!\n"); | ||
417 | } | ||
418 | else | ||
419 | { | ||
420 | gcry_mpi_dump (result); | ||
421 | gcry_mpi_release (result); | ||
422 | } | ||
423 | ok = -1; | ||
424 | } | ||
425 | else | ||
426 | { //currently not used, but if we get more info due to MESH we will need this | ||
427 | LOG (GNUNET_ERROR_TYPE_WARNING, "Error during computation of vector product, return code: %d\n", product_len); | ||
428 | ok = -1; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | // Not shutting down this time, only for this regression test. We have shutdown explicitly earlier. | ||
433 | // Shutting down again is causing problems. | ||
434 | |||
435 | // if(peer2.vh != NULL) | ||
436 | // { | ||
437 | // GNUNET_SCHEDULER_add_now(&do_shutdown, &peer2); | ||
438 | // } | ||
439 | return; | ||
440 | } | ||
441 | |||
442 | |||
443 | static void | ||
444 | requester_request (void *cls, | ||
445 | const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
446 | { | ||
447 | GNUNET_assert (peer2.vh != NULL); | ||
448 | |||
449 | unsigned int i; | ||
450 | uint16_t element_count = 0; | ||
451 | uint16_t mask_length = 0; | ||
452 | char * begin = input_elements_peer2; | ||
453 | char * end; | ||
454 | int32_t element; | ||
455 | struct GNUNET_VECTORPRODUCT_QueueEntry *qe; | ||
456 | struct GNUNET_HashCode key; | ||
457 | int exit_loop = 0; | ||
458 | |||
459 | GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key); | ||
460 | |||
461 | /* Read input_elements_peer2, and put in elements_peer2 array */ | ||
462 | exit_loop = 0; | ||
463 | do | ||
464 | { | ||
465 | unsigned int mcount = element_count; | ||
466 | //ignore empty rows of ,,,,,, | ||
467 | while (*begin == ',') | ||
468 | begin++; | ||
469 | // get the length of the current element and replace , with null | ||
470 | for (end = begin; *end && *end != ','; end++); | ||
471 | |||
472 | if (*end == '\0') | ||
473 | exit_loop = 1; | ||
474 | |||
475 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
476 | { | ||
477 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
478 | ok = -1; | ||
479 | return; | ||
480 | } | ||
481 | |||
482 | GNUNET_array_append (elements_peer2, mcount, element); | ||
483 | element_count++; | ||
484 | |||
485 | begin = ++end; | ||
486 | } | ||
487 | while (!exit_loop && element_count < max_mids); | ||
488 | GNUNET_assert (elements_peer2 != NULL); | ||
489 | GNUNET_assert (element_count >= 1); | ||
490 | |||
491 | /* Read input_mask_peer2 and read in mask_peer2 array */ | ||
492 | mask_length = element_count / 8 + (element_count % 8 ? 1 : 0); | ||
493 | mask_peer2 = GNUNET_malloc ((element_count / 8) + 2); | ||
494 | GNUNET_assert (NULL != mask_peer2); | ||
495 | if (NULL != input_mask_peer2) | ||
496 | { | ||
497 | begin = input_mask_peer2; | ||
498 | unsigned short mask_count = 0; | ||
499 | exit_loop = 0; | ||
500 | |||
501 | do | ||
502 | { | ||
503 | //ignore empty rows of ,,,,,, | ||
504 | while (* begin == ',') | ||
505 | begin++; | ||
506 | // get the length of the current element and replace , with null | ||
507 | // gnunet_ascii-armor uses base32, thus we can use , as separator! | ||
508 | for (end = begin; *end && *end != ','; end++); | ||
509 | |||
510 | if (*end == '\0') | ||
511 | exit_loop = 1; | ||
512 | |||
513 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
514 | { | ||
515 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
516 | ok = -1; | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | GNUNET_assert (mask_count <= element_count); | ||
521 | |||
522 | if (element) | ||
523 | mask_peer2[mask_count / 8] = mask_peer2[mask_count / 8] | 1 << (mask_count % 8); | ||
524 | |||
525 | mask_count++; | ||
526 | begin = ++end; | ||
527 | } | ||
528 | while (!exit_loop); | ||
529 | // +1 to see if we would have more data, which would indicate malformed/superficial input | ||
530 | GNUNET_assert (mask_count == element_count); | ||
531 | } | ||
532 | else | ||
533 | { | ||
534 | for (i = 0; i <= mask_length; i++) | ||
535 | mask_peer2[i] = UCHAR_MAX; // all 1's | ||
536 | } | ||
537 | |||
538 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Responder peer key %s\n", &peer1.our_id); | ||
539 | |||
540 | qe = GNUNET_VECTORPRODUCT_request (peer2.vh, | ||
541 | &key, | ||
542 | &peer1.our_id, | ||
543 | element_count, | ||
544 | mask_length, | ||
545 | elements_peer2, mask_peer2, | ||
546 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), | ||
547 | &requester_callback, | ||
548 | NULL); | ||
549 | |||
550 | if (qe == NULL) | ||
551 | { | ||
552 | FPRINTF (stderr, "%s", _ ("Could not send request to vectorproduct service! Exitting!")); | ||
553 | ok = -1; | ||
554 | return; | ||
555 | } | ||
556 | |||
557 | /** | ||
558 | * For regression, we shutdown the initiator peer, peer2, one second after | ||
559 | * issuing a request. Hopefully, peer1 notices that the tunnel has been | ||
560 | * been destroyed, and will shutdown cleanly. | ||
561 | */ | ||
562 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, &peer2); | ||
563 | |||
564 | return; | ||
565 | } | ||
566 | |||
567 | |||
568 | /** | ||
569 | * Function prepares the message to be sent by peer1 to its vectorproduct service | ||
570 | * to prepare response, and wait for a request session to be initiated by peer1 | ||
571 | */ | ||
572 | static void | ||
573 | responder_prepare_response (void *cls, | ||
574 | const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
575 | { | ||
576 | GNUNET_assert (peer1.vh != NULL); | ||
577 | |||
578 | uint16_t element_count = 0; | ||
579 | char * begin = input_elements_peer1; | ||
580 | char * end; | ||
581 | int32_t element; | ||
582 | |||
583 | struct GNUNET_VECTORPRODUCT_QueueEntry *qe; | ||
584 | |||
585 | struct GNUNET_HashCode key; | ||
586 | GNUNET_CRYPTO_hash (input_key, strlen (input_key), &key); | ||
587 | |||
588 | int exit_loop = 0; | ||
589 | /* Read input_elements_peer1, and put in elements_peer1 array */ | ||
590 | do | ||
591 | { | ||
592 | unsigned int mcount = element_count; | ||
593 | //ignore empty rows of ,,,,,, | ||
594 | while (*begin == ',') | ||
595 | begin++; | ||
596 | // get the length of the current element and replace , with null | ||
597 | for (end = begin; *end && *end != ','; end++); | ||
598 | |||
599 | if (*end == '\0') | ||
600 | exit_loop = 1; | ||
601 | |||
602 | if (1 != sscanf (begin, "%" SCNd32, &element)) | ||
603 | { | ||
604 | FPRINTF (stderr, _ ("Could not convert `%s' to int32_t.\n"), begin); | ||
605 | ok = -1; | ||
606 | return; | ||
607 | } | ||
608 | |||
609 | GNUNET_array_append (elements_peer1, mcount, element); | ||
610 | element_count++; | ||
611 | |||
612 | begin = ++end; | ||
613 | } | ||
614 | while (!exit_loop && element_count < max_mids); | ||
615 | |||
616 | GNUNET_assert (elements_peer1 != NULL); | ||
617 | GNUNET_assert (element_count >= 1); | ||
618 | |||
619 | qe = GNUNET_VECTORPRODUCT_prepare_response (peer1.vh, | ||
620 | &key, | ||
621 | element_count, | ||
622 | elements_peer1, | ||
623 | GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), | ||
624 | &responder_callback, | ||
625 | NULL); | ||
626 | |||
627 | if (qe == NULL) | ||
628 | { | ||
629 | FPRINTF (stderr, "%s", _ ("Could not send request to vectorproduct service! Exitting!")); | ||
630 | ok = -1; | ||
631 | return; | ||
632 | } | ||
633 | |||
634 | // connect the second peer | ||
635 | setup_state = PEER2_VECTORPRODUCT_CONNECT; | ||
636 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1), &connect_peer, &peer2); | ||
637 | |||
638 | // while the service is waiting for a matching request, disconnect the test client | ||
639 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &do_shutdown, &peer1); | ||
640 | |||
641 | return; | ||
642 | } | ||
643 | |||
644 | |||
645 | /** | ||
646 | * Adapter function called to destroy a connection to | ||
647 | * a service. This function is called when GNUNET_TESTBED_operation_done is | ||
648 | * called for peer->op, which holds the handle for GNUNET_TESTBED_service_connect | ||
649 | * operation. | ||
650 | * | ||
651 | * @param cls closure | ||
652 | * @param op_result service handle returned from the connect adapter | ||
653 | */ | ||
654 | static void | ||
655 | vectorproduct_da (void *cls, void *op_result) | ||
656 | { | ||
657 | struct PeerData* peer = (struct PeerData*) cls; | ||
658 | |||
659 | GNUNET_VECTORPRODUCT_disconnect (peer->vh); | ||
660 | peer->vh = NULL; | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | |||
665 | /** | ||
666 | * Adapter function called to establish a connection to | ||
667 | * a service. This function is called to by GNUNET_TESTBED_service_connect. | ||
668 | * | ||
669 | * @param cls closure | ||
670 | * @param cfg configuration of the peer to connect to; will be available until | ||
671 | * GNUNET_TESTBED_operation_done() is called on the operation returned | ||
672 | * from GNUNET_TESTBED_service_connect() | ||
673 | * @return service handle to return in 'op_result', NULL on error | ||
674 | */ | ||
675 | static void * | ||
676 | vectorproduct_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) | ||
677 | { | ||
678 | struct PeerData *p = cls; | ||
679 | |||
680 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %u (`%s') started\n", (&peer1 == p) ? 1 : 2, | ||
681 | GNUNET_i2s (&p->our_id)); | ||
682 | |||
683 | switch (setup_state) | ||
684 | { | ||
685 | case PEER1_VECTORPRODUCT_CONNECT: | ||
686 | peer1.vh = GNUNET_VECTORPRODUCT_connect (cfg); | ||
687 | |||
688 | if (peer1.vh != NULL) | ||
689 | { | ||
690 | /* prepare_response from peer1 */ | ||
691 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &responder_prepare_response, NULL); | ||
692 | } | ||
693 | else | ||
694 | { | ||
695 | ok = -1; | ||
696 | return NULL; | ||
697 | } | ||
698 | |||
699 | return peer1.vh; | ||
700 | |||
701 | case PEER2_VECTORPRODUCT_CONNECT: | ||
702 | /* Actually connect peer 2 to vectorproduct service */ | ||
703 | peer2.vh = GNUNET_VECTORPRODUCT_connect (cfg); | ||
704 | |||
705 | if (peer2.vh != NULL) | ||
706 | { | ||
707 | /* initiate request from peer2 */ | ||
708 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &requester_request, NULL); | ||
709 | } | ||
710 | else | ||
711 | { | ||
712 | ok = -1; | ||
713 | return NULL; | ||
714 | } | ||
715 | |||
716 | return peer2.vh; | ||
717 | default: | ||
718 | GNUNET_assert (0); | ||
719 | } | ||
720 | } | ||
721 | |||
722 | |||
723 | /** | ||
724 | * Helper function to connect a test peer | ||
725 | * | ||
726 | * @param cls void* to struct PeerData of the peer to be connected | ||
727 | * @param tc Task Context | ||
728 | */ | ||
729 | static void | ||
730 | connect_peer (void *cls, | ||
731 | const struct GNUNET_SCHEDULER_TaskContext * tc) | ||
732 | { | ||
733 | struct PeerData *peer = cls; | ||
734 | |||
735 | peer->op = GNUNET_TESTBED_service_connect (peer, peer->peer, "vectorproduct", | ||
736 | NULL, NULL, vectorproduct_ca, | ||
737 | vectorproduct_da, peer); | ||
738 | |||
739 | } | ||
740 | |||
741 | |||
742 | /** | ||
743 | * Callback to be called when the requested peer information is available | ||
744 | * | ||
745 | * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information() | ||
746 | * @param op the operation this callback corresponds to | ||
747 | * @param pinfo the result; will be NULL if the operation has failed | ||
748 | * @param emsg error message if the operation has failed; will be NULL if the | ||
749 | * operation is successfull | ||
750 | */ | ||
751 | static void | ||
752 | peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op_, | ||
753 | const struct GNUNET_TESTBED_PeerInformation *pinfo, | ||
754 | const char *emsg) | ||
755 | { | ||
756 | GNUNET_assert (NULL == emsg); | ||
757 | GNUNET_assert (op == op_); | ||
758 | |||
759 | switch (setup_state) | ||
760 | { | ||
761 | case PEER1_GET_IDENTITY: | ||
762 | { | ||
763 | memcpy (&peer1.our_id, pinfo->result.id, | ||
764 | sizeof (struct GNUNET_PeerIdentity)); | ||
765 | GNUNET_TESTBED_operation_done (op); | ||
766 | |||
767 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 1 id: %s\n", GNUNET_i2s_full | ||
768 | (&peer1.our_id)); | ||
769 | |||
770 | /* Request for peer id of peer 2*/ | ||
771 | setup_state = PEER2_GET_IDENTITY; | ||
772 | op = GNUNET_TESTBED_peer_get_information (peer2.peer, | ||
773 | GNUNET_TESTBED_PIT_IDENTITY, | ||
774 | &peerinfo_cb, NULL); | ||
775 | } | ||
776 | break; | ||
777 | case PEER2_GET_IDENTITY: | ||
778 | { | ||
779 | memcpy (&peer2.our_id, pinfo->result.id, | ||
780 | sizeof (struct GNUNET_PeerIdentity)); | ||
781 | GNUNET_TESTBED_operation_done (op); | ||
782 | |||
783 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer 2 id: %s\n", GNUNET_i2s_full | ||
784 | (&peer2.our_id)); | ||
785 | |||
786 | /* Connect peer 1 to vectorproduct service */ | ||
787 | setup_state = PEER1_VECTORPRODUCT_CONNECT; | ||
788 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &connect_peer, &peer1); | ||
789 | } | ||
790 | break; | ||
791 | default: | ||
792 | GNUNET_assert (0); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | |||
797 | /** | ||
798 | * Signature of a main function for a testcase. | ||
799 | * | ||
800 | * @param cls closure | ||
801 | * @param num_peers number of peers in 'peers' | ||
802 | * @param peers handle to peers run in the testbed | ||
803 | */ | ||
804 | static void | ||
805 | test_master (void *cls, unsigned int num_peers, | ||
806 | struct GNUNET_TESTBED_Peer **peers) | ||
807 | { | ||
808 | GNUNET_assert (NULL != peers); | ||
809 | GNUNET_assert (NULL != peers[0]); | ||
810 | GNUNET_assert (NULL != peers[1]); | ||
811 | peer1.peer = peers[0]; | ||
812 | peer2.peer = peers[1]; | ||
813 | |||
814 | /* Get the peer identity and configuration of peer 1 */ | ||
815 | setup_state = PEER1_GET_IDENTITY; | ||
816 | op = GNUNET_TESTBED_peer_get_information (peer1.peer, | ||
817 | GNUNET_TESTBED_PIT_IDENTITY, | ||
818 | &peerinfo_cb, NULL); | ||
819 | |||
820 | abort_task = | ||
821 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply | ||
822 | (GNUNET_TIME_UNIT_SECONDS, 20), &do_abort, | ||
823 | NULL); | ||
824 | } | ||
825 | |||
826 | |||
827 | /** | ||
828 | * Main function | ||
829 | */ | ||
830 | int | ||
831 | main (int argc, char **argv) | ||
832 | { | ||
833 | uint64_t event_mask; | ||
834 | |||
835 | ok = GNUNET_NO; | ||
836 | event_mask = 0; | ||
837 | event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED); | ||
838 | max_mids = (GNUNET_SERVER_MAX_MESSAGE_SIZE - sizeof (struct GNUNET_MessageHeader)) | ||
839 | / sizeof (struct GNUNET_CRYPTO_HashAsciiEncoded) - 1; | ||
840 | |||
841 | (void) GNUNET_TESTBED_test_run ("test_vectorproduct_api_regression", | ||
842 | "test_vectorproduct_api_data.conf", | ||
843 | NUM_PEERS, event_mask, &controller_event_cb, | ||
844 | NULL, | ||
845 | &test_master, NULL); | ||
846 | |||
847 | if (GNUNET_SYSERR == ok) | ||
848 | return 1; | ||
849 | return 0; | ||
850 | } | ||
851 | |||
852 | |||