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