paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / psyc / test_psyc.c
1 /*
2  * This file is part of GNUnet
3  * Copyright (C) 2013 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
19 /**
20  * @file psyc/test_psyc.c
21  * @brief Tests for the PSYC API.
22  * @author Gabor X Toth
23  * @author Christian Grothoff
24  */
25
26 #include <inttypes.h>
27
28 #include "platform.h"
29 #include "gnunet_crypto_lib.h"
30 #include "gnunet_common.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_testing_lib.h"
33 #include "gnunet_psyc_util_lib.h"
34 #include "gnunet_psyc_service.h"
35
36 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
37
38 /**
39  * Return value from 'main'.
40  */
41 static int res;
42
43 static const struct GNUNET_CONFIGURATION_Handle *cfg;
44
45 static struct GNUNET_PeerIdentity this_peer;
46
47 /**
48  * Handle for task for timeout termination.
49  */
50 static struct GNUNET_SCHEDULER_Task * end_badly_task;
51
52 static struct GNUNET_PSYC_Master *mst;
53 static struct GNUNET_PSYC_Slave *slv;
54
55 static struct GNUNET_PSYC_Channel *mst_chn, *slv_chn;
56
57 static struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key;
58 static struct GNUNET_CRYPTO_EcdsaPrivateKey *slave_key;
59
60 static struct GNUNET_CRYPTO_EddsaPublicKey channel_pub_key;
61 static struct GNUNET_CRYPTO_EcdsaPublicKey slave_pub_key;
62
63 struct TransmitClosure
64 {
65   struct GNUNET_PSYC_MasterTransmitHandle *mst_tmit;
66   struct GNUNET_PSYC_SlaveTransmitHandle *slv_tmit;
67   struct GNUNET_PSYC_Environment *env;
68   struct GNUNET_PSYC_Modifier *mod;
69   char *data[16];
70   const char *mod_value;
71   size_t mod_value_size;
72   uint8_t data_delay[16];
73   uint8_t data_count;
74   uint8_t paused;
75   uint8_t n;
76 };
77
78 static struct TransmitClosure *tmit;
79
80 static uint8_t join_req_count, end_count;
81
82 enum
83 {
84   TEST_NONE                         = 0,
85   TEST_MASTER_START                 = 1,
86   TEST_SLAVE_JOIN_REJECT            = 2,
87   TEST_SLAVE_JOIN_ACCEPT            = 3,
88   TEST_SLAVE_ADD                    = 4,
89   TEST_SLAVE_REMOVE                 = 5,
90   TEST_SLAVE_TRANSMIT               = 6,
91   TEST_MASTER_TRANSMIT              = 7,
92   TEST_MASTER_HISTORY_REPLAY_LATEST = 8,
93   TEST_SLAVE_HISTORY_REPLAY_LATEST  = 9,
94   TEST_MASTER_HISTORY_REPLAY       = 10,
95   TEST_SLAVE_HISTORY_REPLAY        = 11,
96   TEST_MASTER_STATE_GET            = 12,
97   TEST_SLAVE_STATE_GET             = 13,
98   TEST_MASTER_STATE_GET_PREFIX     = 14,
99   TEST_SLAVE_STATE_GET_PREFIX      = 15,
100 } test;
101
102
103 static void
104 master_transmit ();
105
106 static void
107 master_history_replay_latest ();
108
109
110 static void
111 master_stopped (void *cls)
112 {
113   if (NULL != tmit)
114   {
115     GNUNET_PSYC_env_destroy (tmit->env);
116     GNUNET_free (tmit);
117     tmit = NULL;
118   }
119   GNUNET_SCHEDULER_shutdown ();
120 }
121
122
123 static void
124 slave_parted (void *cls)
125 {
126   if (NULL != mst)
127   {
128     GNUNET_PSYC_master_stop (mst, GNUNET_NO, &master_stopped, NULL);
129     mst = NULL;
130   }
131   else
132     master_stopped (NULL);
133 }
134
135
136 /**
137  * Clean up all resources used.
138  */
139 static void
140 cleanup ()
141 {
142   if (NULL != slv)
143   {
144     GNUNET_PSYC_slave_part (slv, GNUNET_NO, &slave_parted, NULL);
145     slv = NULL;
146   }
147   else
148     slave_parted (NULL);
149 }
150
151
152 /**
153  * Terminate the test case (failure).
154  *
155  * @param cls NULL
156  */
157 static void
158 end_badly (void *cls)
159 {
160   res = 1;
161   cleanup ();
162   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n");
163 }
164
165
166 /**
167  * Terminate the test case (success).
168  *
169  * @param cls NULL
170  */
171 static void
172 end_normally (void *cls)
173 {
174   res = 0;
175   cleanup ();
176   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test PASSED.\n");
177 }
178
179
180 /**
181  * Finish the test case (successfully).
182  */
183 static void
184 end ()
185 {
186   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Ending tests.\n");
187
188   if (end_badly_task != NULL)
189   {
190     GNUNET_SCHEDULER_cancel (end_badly_task);
191     end_badly_task = NULL;
192   }
193   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
194                                 &end_normally, NULL);
195 }
196
197
198 static void
199 master_message_cb (void *cls, const struct GNUNET_PSYC_MessageHeader *msg)
200 {
201   GNUNET_assert (NULL != msg);
202   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
203               "Test #%d: Master got PSYC message fragment of size %u "
204               "belonging to message ID %" PRIu64 " with flags %x\n",
205               test, ntohs (msg->header.size),
206               GNUNET_ntohll (msg->message_id), ntohl (msg->flags));
207   // FIXME
208 }
209
210
211 static void
212 master_message_part_cb (void *cls, const struct GNUNET_PSYC_MessageHeader *msg,
213                         const struct GNUNET_MessageHeader *pmsg)
214 {
215   GNUNET_assert (NULL != msg && NULL != pmsg);
216
217   uint64_t message_id = GNUNET_ntohll (msg->message_id);
218   uint32_t flags = ntohl (msg->flags);
219
220   uint16_t type = ntohs (pmsg->type);
221   uint16_t size = ntohs (pmsg->size);
222
223   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
224               "Test #%d: Master got message part of type %u and size %u "
225               "belonging to message ID %" PRIu64 " with flags %x\n",
226               test, type, size, message_id, flags);
227
228   switch (test)
229   {
230   case TEST_SLAVE_TRANSMIT:
231     if (GNUNET_PSYC_MESSAGE_REQUEST != flags)
232     {
233       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
234                   "Test #%d: Unexpected request flags: %x" PRIu32 "\n",
235                   test, flags);
236       GNUNET_assert (0);
237       return;
238     }
239     // FIXME: check rest of message
240
241     if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type)
242       master_transmit ();
243     break;
244
245   case TEST_MASTER_TRANSMIT:
246     if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type && 2 == ++end_count)
247       master_history_replay_latest ();
248     break;
249
250   case TEST_MASTER_HISTORY_REPLAY:
251   case TEST_MASTER_HISTORY_REPLAY_LATEST:
252     if (GNUNET_PSYC_MESSAGE_HISTORIC != flags)
253     {
254       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
255                   "Test #%d: Unexpected flags for historic message: %x" PRIu32 "\n",
256                   test, flags);
257       GNUNET_assert (0);
258       return;
259     }
260     break;
261
262   default:
263     GNUNET_assert (0);
264   }
265 }
266
267
268 static void
269 slave_message_cb (void *cls, const struct GNUNET_PSYC_MessageHeader *msg)
270 {
271   GNUNET_assert (NULL != msg);
272   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
273               "Test #%d: Slave got PSYC message fragment of size %u "
274               "belonging to message ID %" PRIu64 " with flags %x\n",
275               test, ntohs (msg->header.size),
276               GNUNET_ntohll (msg->message_id), ntohl (msg->flags));
277   // FIXME
278 }
279
280
281 static void
282 slave_message_part_cb (void *cls,
283                        const struct GNUNET_PSYC_MessageHeader *msg,
284                        const struct GNUNET_MessageHeader *pmsg)
285 {
286   GNUNET_assert (NULL != msg && NULL != pmsg);
287
288   uint64_t message_id = GNUNET_ntohll (msg->message_id);
289   uint32_t flags = ntohl (msg->flags);
290
291   uint16_t type = ntohs (pmsg->type);
292   uint16_t size = ntohs (pmsg->size);
293
294   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
295               "Test #%d: Slave got message part of type %u and size %u "
296               "belonging to message ID %" PRIu64 " with flags %x\n",
297               test, type, size, message_id, flags);
298
299   switch (test)
300   {
301   case TEST_MASTER_TRANSMIT:
302     if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END == type && 2 == ++end_count)
303       master_history_replay_latest ();
304     break;
305
306   case TEST_SLAVE_HISTORY_REPLAY:
307   case TEST_SLAVE_HISTORY_REPLAY_LATEST:
308     if (GNUNET_PSYC_MESSAGE_HISTORIC != flags)
309     {
310       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
311                   "Test #%d: Unexpected flags for historic message: %x" PRIu32 "\n",
312                   test, flags);
313       GNUNET_assert (0);
314       return;
315     }
316     break;
317
318   default:
319     GNUNET_assert (0);
320   }
321 }
322
323
324 static void
325 state_get_var (void *cls, const struct GNUNET_MessageHeader *mod,
326                const char *name, const void *value,
327                uint32_t value_size, uint32_t full_value_size)
328 {
329   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
330               "Got state var: %s\n%.*s\n",
331               name,
332               (int) value_size,
333               (const char *) value);
334 }
335
336
337 /*** Slave state_get_prefix() ***/
338
339 static void
340 slave_state_get_prefix_result (void *cls, int64_t result,
341                                const void *err_msg, uint16_t err_msg_size)
342 {
343   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
344               "Test #%d: slave_state_get_prefix:\t%" PRId64 " (%.*s)\n",
345               test, result,
346               (int) err_msg_size,
347               (const char *) err_msg);
348   // FIXME: GNUNET_assert (2 == result);
349   end ();
350 }
351
352
353 static void
354 slave_state_get_prefix ()
355 {
356   test = TEST_SLAVE_STATE_GET_PREFIX;
357   GNUNET_PSYC_channel_state_get_prefix (slv_chn, "_foo", state_get_var,
358                                         slave_state_get_prefix_result, NULL);
359 }
360
361
362 /*** Master state_get_prefix() ***/
363
364
365 static void
366 master_state_get_prefix_result (void *cls, int64_t result,
367                                 const void *err_msg, uint16_t err_msg_size)
368 {
369   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
370               "Test #%d: master_state_get_prefix:\t%" PRId64 " (%s)\n",
371               test, result, (char *) err_msg);
372   // FIXME: GNUNET_assert (2 == result);
373   slave_state_get_prefix ();
374 }
375
376
377 static void
378 master_state_get_prefix ()
379 {
380   test = TEST_MASTER_STATE_GET_PREFIX;
381   GNUNET_PSYC_channel_state_get_prefix (mst_chn, "_foo", state_get_var,
382                                         master_state_get_prefix_result, NULL);
383 }
384
385
386 /*** Slave state_get() ***/
387
388
389 static void
390 slave_state_get_result (void *cls, int64_t result,
391                         const void *err_msg, uint16_t err_msg_size)
392 {
393   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
394               "Test #%d: slave_state_get:\t%" PRId64 " (%.*s)\n",
395               test, result, err_msg_size, (char *) err_msg);
396   // FIXME: GNUNET_assert (2 == result);
397   master_state_get_prefix ();
398 }
399
400
401 static void
402 slave_state_get ()
403 {
404   test = TEST_SLAVE_STATE_GET;
405   GNUNET_PSYC_channel_state_get (slv_chn, "_foo_bar_baz", state_get_var,
406                                  slave_state_get_result, NULL);
407 }
408
409
410 /*** Master state_get() ***/
411
412
413 static void
414 master_state_get_result (void *cls, int64_t result,
415                          const void *err_msg, uint16_t err_msg_size)
416 {
417   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
418               "Test #%d: master_state_get:\t%" PRId64 " (%.*s)\n",
419               test, result, err_msg_size, (char *) err_msg);
420   // FIXME: GNUNET_assert (1 == result);
421   slave_state_get ();
422 }
423
424
425 static void
426 master_state_get ()
427 {
428   test = TEST_MASTER_STATE_GET;
429   GNUNET_PSYC_channel_state_get (mst_chn, "_foo_bar_baz", state_get_var,
430                                  master_state_get_result, NULL);
431 }
432
433
434 /*** Slave history_replay() ***/
435
436 static void
437 slave_history_replay_result (void *cls, int64_t result,
438                              const void *err_msg, uint16_t err_msg_size)
439 {
440   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
441               "Test #%d: slave_history_replay:\t%" PRId64 " (%.*s)\n",
442               test, result,
443               (int) err_msg_size,
444               (const char *) err_msg);
445   GNUNET_assert (9 == result);
446
447   master_state_get ();
448 }
449
450
451 static void
452 slave_history_replay ()
453 {
454   test = TEST_SLAVE_HISTORY_REPLAY;
455   GNUNET_PSYC_channel_history_replay (slv_chn, 1, 1, "",
456                                       GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
457                                       slave_message_cb,
458                                       slave_message_part_cb,
459                                       slave_history_replay_result, NULL);
460 }
461
462
463 /*** Master history_replay() ***/
464
465
466 static void
467 master_history_replay_result (void *cls, int64_t result,
468                               const void *err_msg, uint16_t err_msg_size)
469 {
470   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
471               "Test #%d: master_history_replay:\t%" PRId64 " (%.*s)\n",
472               test, result,
473               (int) err_msg_size,
474               (const char *) err_msg);
475   GNUNET_assert (9 == result);
476
477   slave_history_replay ();
478 }
479
480
481 static void
482 master_history_replay ()
483 {
484   test = TEST_MASTER_HISTORY_REPLAY;
485   GNUNET_PSYC_channel_history_replay (mst_chn, 1, 1, "",
486                                       GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
487                                       master_message_cb,
488                                       master_message_part_cb,
489                                       master_history_replay_result, NULL);
490 }
491
492
493 /*** Slave history_replay_latest() ***/
494
495
496 static void
497 slave_history_replay_latest_result (void *cls, int64_t result,
498                                     const void *err_msg, uint16_t err_msg_size)
499 {
500   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
501               "Test #%d: slave_history_replay_latest:\t%" PRId64 " (%.*s)\n",
502               test, result,
503               (int) err_msg_size,
504               (const char *) err_msg);
505   GNUNET_assert (9 == result);
506
507   master_history_replay ();
508 }
509
510
511 static void
512 slave_history_replay_latest ()
513 {
514   test = TEST_SLAVE_HISTORY_REPLAY_LATEST;
515   GNUNET_PSYC_channel_history_replay_latest (slv_chn, 1, "",
516                                              GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
517                                              &slave_message_cb,
518                                              &slave_message_part_cb,
519                                              &slave_history_replay_latest_result,
520                                              NULL);
521 }
522
523
524 /*** Master history_replay_latest() ***/
525
526
527 static void
528 master_history_replay_latest_result (void *cls, int64_t result,
529                                      const void *err_msg, uint16_t err_msg_size)
530 {
531   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
532               "Test #%d: master_history_replay_latest:\t%" PRId64 " (%.*s)\n",
533               test, result, err_msg_size, (char *) err_msg);
534   GNUNET_assert (9 == result);
535
536   slave_history_replay_latest ();
537 }
538
539
540 static void
541 master_history_replay_latest ()
542 {
543   test = TEST_MASTER_HISTORY_REPLAY_LATEST;
544   GNUNET_PSYC_channel_history_replay_latest (mst_chn, 1, "",
545                                              GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
546                                              &master_message_cb,
547                                              &master_message_part_cb,
548                                              &master_history_replay_latest_result,
549                                              NULL);
550 }
551
552
553 static void
554 transmit_resume (void *cls)
555 {
556   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
557               "Test #%d: Transmission resumed.\n", test);
558   struct TransmitClosure *tmit = cls;
559   if (NULL != tmit->mst_tmit)
560     GNUNET_PSYC_master_transmit_resume (tmit->mst_tmit);
561   else
562     GNUNET_PSYC_slave_transmit_resume (tmit->slv_tmit);
563 }
564
565
566 static int
567 tmit_notify_data (void *cls, uint16_t *data_size, void *data)
568 {
569   struct TransmitClosure *tmit = cls;
570   if (0 == tmit->data_count)
571   {
572     *data_size = 0;
573     return GNUNET_YES;
574   }
575
576   uint16_t size = strlen (tmit->data[tmit->n]);
577   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
578               "Test #%d: Transmit notify data: %u bytes available, "
579               "processing fragment %u/%u (size %u).\n",
580               test, *data_size, tmit->n + 1, tmit->data_count, size);
581   if (*data_size < size)
582   {
583     *data_size = 0;
584     GNUNET_assert (0);
585     return GNUNET_SYSERR;
586   }
587
588   if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
589   {
590     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
591                 "Test #%d: Transmission paused.\n", test);
592     tmit->paused = GNUNET_YES;
593     GNUNET_SCHEDULER_add_delayed (
594       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
595                                      tmit->data_delay[tmit->n]),
596       &transmit_resume, tmit);
597     *data_size = 0;
598     return GNUNET_NO;
599   }
600   tmit->paused = GNUNET_NO;
601
602   *data_size = size;
603   GNUNET_memcpy (data, tmit->data[tmit->n], size);
604
605   return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
606 }
607
608
609 static int
610 tmit_notify_mod (void *cls, uint16_t *data_size, void *data, uint8_t *oper,
611                  uint32_t *full_value_size)
612 {
613   struct TransmitClosure *tmit = cls;
614   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
615               "Test #%d: Transmit notify modifier: %u bytes available, "
616               "%u modifiers left to process.\n",
617               test, *data_size, (unsigned int) GNUNET_PSYC_env_get_count (tmit->env));
618
619   uint16_t name_size = 0;
620   size_t value_size = 0;
621   const char *value = NULL;
622
623   if (NULL != oper && NULL != tmit->mod)
624   { /* New modifier */
625     tmit->mod = tmit->mod->next;
626     if (NULL == tmit->mod)
627     { /* No more modifiers, continue with data */
628       *data_size = 0;
629       return GNUNET_YES;
630     }
631
632     GNUNET_assert (tmit->mod->value_size < UINT32_MAX);
633     *full_value_size = tmit->mod->value_size;
634     *oper = tmit->mod->oper;
635     name_size = strlen (tmit->mod->name);
636
637     if (name_size + 1 + tmit->mod->value_size <= *data_size)
638     {
639       *data_size = name_size + 1 + tmit->mod->value_size;
640     }
641     else
642     {
643       tmit->mod_value_size = tmit->mod->value_size;
644       value_size = *data_size - name_size - 1;
645       tmit->mod_value_size -= value_size;
646       tmit->mod_value = tmit->mod->value + value_size;
647     }
648
649     GNUNET_memcpy (data, tmit->mod->name, name_size);
650     ((char *)data)[name_size] = '\0';
651     GNUNET_memcpy ((char *)data + name_size + 1, tmit->mod->value, value_size);
652   }
653   else if (NULL != tmit->mod_value && 0 < tmit->mod_value_size)
654   { /* Modifier continuation */
655     value = tmit->mod_value;
656     if (tmit->mod_value_size <= *data_size)
657     {
658       value_size = tmit->mod_value_size;
659       tmit->mod_value = NULL;
660     }
661     else
662     {
663       value_size = *data_size;
664       tmit->mod_value += value_size;
665     }
666     tmit->mod_value_size -= value_size;
667
668     if (*data_size < value_size)
669     {
670       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671                   "value larger than buffer: %u < %zu\n",
672                   *data_size, value_size);
673       *data_size = 0;
674       return GNUNET_NO;
675     }
676
677     *data_size = value_size;
678     GNUNET_memcpy (data, value, value_size);
679   }
680
681   return GNUNET_NO;
682 }
683
684
685 static void
686 slave_join ();
687
688
689 static void
690 slave_transmit ()
691 {
692   test = TEST_SLAVE_TRANSMIT;
693   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
694               "Test #%d: Slave sending request to master.\n", test);
695
696   tmit = GNUNET_new (struct TransmitClosure);
697   tmit->env = GNUNET_PSYC_env_create ();
698   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
699                               "_abc", "abc def", 7);
700   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
701                               "_abc_def", "abc def ghi", 11);
702   tmit->mod = GNUNET_PSYC_env_head (tmit->env);
703   tmit->n = 0;
704   tmit->data[0] = "slave test";
705   tmit->data_count = 1;
706   tmit->slv_tmit
707     = GNUNET_PSYC_slave_transmit (slv, "_request_test", &tmit_notify_mod,
708                                   &tmit_notify_data, tmit,
709                                   GNUNET_PSYC_SLAVE_TRANSMIT_NONE);
710 }
711
712
713 static void
714 slave_remove_cb (void *cls, int64_t result,
715                  const void *err_msg, uint16_t err_msg_size)
716 {
717   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
718               "Test #%d: slave_remove:\t%" PRId64 " (%.*s)\n",
719               test, result, err_msg_size, (char *) err_msg);
720
721   slave_transmit ();
722 }
723
724
725 static void
726 slave_remove ()
727 {
728   test = TEST_SLAVE_REMOVE;
729   struct GNUNET_PSYC_Channel *chn = GNUNET_PSYC_master_get_channel (mst);
730   GNUNET_PSYC_channel_slave_remove (chn, &slave_pub_key, 2,
731                                     &slave_remove_cb, chn);
732 }
733
734
735 static void
736 slave_add_cb (void *cls, int64_t result,
737               const void *err_msg, uint16_t err_msg_size)
738 {
739   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
740               "Test #%d: slave_add:\t%" PRId64 " (%.*s)\n",
741               test, result, err_msg_size, (char *) err_msg);
742   slave_remove ();
743 }
744
745
746 static void
747 slave_add ()
748 {
749   test = TEST_SLAVE_ADD;
750   struct GNUNET_PSYC_Channel *chn = GNUNET_PSYC_master_get_channel (mst);
751   GNUNET_PSYC_channel_slave_add (chn, &slave_pub_key, 2, 2, &slave_add_cb, chn);
752 }
753
754
755 static void
756 schedule_second_slave_join (void *cls)
757 {
758   slave_join (TEST_SLAVE_JOIN_ACCEPT);
759 }
760
761
762 static void
763 first_slave_parted (void *cls)
764 {
765   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First slave parted.\n");
766   GNUNET_SCHEDULER_add_now (&schedule_second_slave_join, NULL);
767 }
768
769
770 static void
771 schedule_first_slave_part (void *cls)
772 {
773   GNUNET_PSYC_slave_part (slv, GNUNET_NO, &first_slave_parted, NULL);
774 }
775
776
777 static void
778 join_decision_cb (void *cls,
779                   const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
780                   int is_admitted,
781                   const struct GNUNET_PSYC_Message *join_msg)
782 {
783   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
784               "Test #%d: Slave got join decision: %d\n", test, is_admitted);
785
786   switch (test)
787   {
788   case TEST_SLAVE_JOIN_REJECT:
789     GNUNET_assert (0 == is_admitted);
790     GNUNET_assert (1 == join_req_count);
791     GNUNET_SCHEDULER_add_now (&schedule_first_slave_part, NULL);
792     break;
793
794   case TEST_SLAVE_JOIN_ACCEPT:
795     GNUNET_assert (1 == is_admitted);
796     GNUNET_assert (2 == join_req_count);
797     slave_add ();
798     break;
799
800   default:
801     GNUNET_break (0);
802   }
803 }
804
805
806 static void
807 join_request_cb (void *cls,
808                  const struct GNUNET_PSYC_JoinRequestMessage *req,
809                  const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
810                  const struct GNUNET_PSYC_Message *join_msg,
811                  struct GNUNET_PSYC_JoinHandle *jh)
812 {
813   struct GNUNET_HashCode slave_key_hash;
814   GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
815   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
816               "Test #%d: Got join request #%u from %s.\n",
817               test, join_req_count, GNUNET_h2s (&slave_key_hash));
818
819   /* Reject first request */
820   int is_admitted = (0 < join_req_count++) ? GNUNET_YES : GNUNET_NO;
821   GNUNET_PSYC_join_decision (jh, is_admitted, 0, NULL, NULL);
822 }
823
824
825 static void
826 slave_connect_cb (void *cls, int result, uint64_t max_message_id)
827 {
828   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
829               "Test #%d: Slave connected: %d, max_message_id: %" PRIu64 "\n",
830               test, result, max_message_id);
831   GNUNET_assert (TEST_SLAVE_JOIN_REJECT == test || TEST_SLAVE_JOIN_ACCEPT == test);
832   GNUNET_assert (GNUNET_OK == result || GNUNET_NO == result);
833 }
834
835
836 static void
837 slave_join (int t)
838 {
839   test = t;
840   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
841               "Test #%d: Joining slave.\n", t);
842
843   struct GNUNET_PeerIdentity origin = this_peer;
844   struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
845   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN,
846                               "_foo", "bar baz", 7);
847   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN,
848                               "_foo_bar", "foo bar baz", 11);
849   struct GNUNET_PSYC_Message *
850     join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 9);
851
852   slv = GNUNET_PSYC_slave_join (cfg,
853                                 &channel_pub_key,
854                                 slave_key,
855                                 GNUNET_PSYC_SLAVE_JOIN_NONE,
856                                 &origin,
857                                 0,
858                                 NULL,
859                                 &slave_message_cb,
860                                 &slave_message_part_cb,
861                                 &slave_connect_cb,
862                                 &join_decision_cb,
863                                 NULL,
864                                 join_msg);
865   GNUNET_free (join_msg);
866   slv_chn = GNUNET_PSYC_slave_get_channel (slv);
867   GNUNET_PSYC_env_destroy (env);
868 }
869
870
871 static void
872 master_transmit ()
873 {
874   test = TEST_MASTER_TRANSMIT;
875   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
876               "Test #%d: Master sending message to all.\n", test);
877   end_count = 0;
878
879   uint32_t i, j;
880
881   char *name_max = "_test_max";
882   uint8_t name_max_size = sizeof ("_test_max");
883   char *val_max = GNUNET_malloc (GNUNET_PSYC_MODIFIER_MAX_PAYLOAD);
884   for (i = 0; i < GNUNET_PSYC_MODIFIER_MAX_PAYLOAD; i++)
885     val_max[i] = (0 == i % 10000) ? '0' + i / 10000 : '.';
886
887   char *name_cont = "_test_cont";
888   uint8_t name_cont_size = sizeof ("_test_cont");
889   char *val_cont = GNUNET_malloc (GNUNET_PSYC_MODIFIER_MAX_PAYLOAD
890                                   + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD);
891   for (i = 0; i < GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size; i++)
892     val_cont[i] = (0 == i % 10000) ? '0' + i / 10000 : ':';
893   for (j = 0; j < GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD; j++, i++)
894     val_cont[i] = (0 == j % 10000) ? '0' + j / 10000 : '!';
895
896   tmit = GNUNET_new (struct TransmitClosure);
897   tmit->env = GNUNET_PSYC_env_create ();
898   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
899                               "_foo", "bar baz", 7);
900   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
901                               name_max, val_max,
902                               GNUNET_PSYC_MODIFIER_MAX_PAYLOAD
903                               - name_max_size);
904   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
905                               "_foo_bar", "foo bar baz", 11);
906   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
907                               name_cont, val_cont,
908                               GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size
909                               + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD);
910   tmit->mod = GNUNET_PSYC_env_head (tmit->env);
911   tmit->data[0] = "foo";
912   tmit->data[1] =  GNUNET_malloc (GNUNET_PSYC_DATA_MAX_PAYLOAD + 1);
913   for (i = 0; i < GNUNET_PSYC_DATA_MAX_PAYLOAD; i++)
914     tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_';
915   tmit->data[2] = "foo bar";
916   tmit->data[3] = "foo bar baz";
917   tmit->data_delay[1] = 3;
918   tmit->data_count = 4;
919   tmit->mst_tmit
920     = GNUNET_PSYC_master_transmit (mst, "_notice_test", &tmit_notify_mod,
921                                    &tmit_notify_data, tmit,
922                                    GNUNET_PSYC_MASTER_TRANSMIT_INC_GROUP_GEN);
923 }
924
925
926 static void
927 master_start_cb (void *cls, int result, uint64_t max_message_id)
928 {
929   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
930               "Test #%d: Master started: %d, max_message_id: %" PRIu64 "\n",
931               test, result, max_message_id);
932   GNUNET_assert (TEST_MASTER_START == test);
933   GNUNET_assert (GNUNET_OK == result || GNUNET_NO == result);
934   slave_join (TEST_SLAVE_JOIN_REJECT);
935 }
936
937
938 static void
939 master_start ()
940 {
941   test = TEST_MASTER_START;
942   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
943               "Test #%d: Starting master.\n", test);
944   mst = GNUNET_PSYC_master_start (cfg, channel_key, GNUNET_PSYC_CHANNEL_PRIVATE,
945                                   &master_start_cb, &join_request_cb,
946                                   &master_message_cb, &master_message_part_cb,
947                                   NULL);
948   mst_chn = GNUNET_PSYC_master_get_channel (mst);
949 }
950
951
952 static void
953 schedule_master_start (void *cls)
954 {
955   master_start ();
956 }
957
958
959 /**
960  * Main function of the test, run from scheduler.
961  *
962  * @param cls NULL
963  * @param cfg configuration we use (also to connect to PSYC service)
964  * @param peer handle to access more of the peer (not used)
965  */
966 static void
967 #if DEBUG_TEST_PSYC
968 run (void *cls, char *const *args, const char *cfgfile,
969      const struct GNUNET_CONFIGURATION_Handle *c)
970 #else
971 run (void *cls,
972      const struct GNUNET_CONFIGURATION_Handle *c,
973      struct GNUNET_TESTING_Peer *peer)
974 #endif
975 {
976   cfg = c;
977   end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
978
979   GNUNET_CRYPTO_get_peer_identity (cfg, &this_peer);
980
981   channel_key = GNUNET_CRYPTO_eddsa_key_create ();
982   slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
983
984   GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
985   GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
986
987 #if DEBUG_TEST_PSYC
988   master_start ();
989 #else
990   /* Allow some time for the services to initialize. */
991   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
992                                 &schedule_master_start, NULL);
993 #endif
994 }
995
996
997 int
998 main (int argc, char *argv[])
999 {
1000   res = 1;
1001 #if DEBUG_TEST_PSYC
1002   const struct GNUNET_GETOPT_CommandLineOption opts[] = {
1003     GNUNET_GETOPT_OPTION_END
1004   };
1005   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psyc",
1006                                        "test-psyc [options]",
1007                                        opts, &run, NULL))
1008     return 1;
1009 #else
1010   if (0 != GNUNET_TESTING_peer_run ("test-psyc", "test_psyc.conf", &run, NULL))
1011     return 1;
1012 #endif
1013   return res;
1014 }
1015
1016 /* end of test_psyc.c */