social needs to start as user service, not system
[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",
340               name,
341               (int) value_size,
342               (const char *) value);
343 }
344
345
346 /*** Slave state_get_prefix() ***/
347
348 static void
349 slave_state_get_prefix_result (void *cls, int64_t result,
350                                const void *err_msg, uint16_t err_msg_size)
351 {
352   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
353               "slave_state_get_prefix:\t%" PRId64 " (%.s)\n",
354               result,
355               (int) err_msg_size,
356               (const char *) err_msg);
357   // FIXME: GNUNET_assert (2 == result);
358   end ();
359 }
360
361
362 static void
363 slave_state_get_prefix ()
364 {
365   test = TEST_SLAVE_STATE_GET_PREFIX;
366   GNUNET_PSYC_channel_state_get_prefix (slv_chn, "_foo", state_get_var,
367                                         slave_state_get_prefix_result, NULL);
368 }
369
370
371 /*** Master state_get_prefix() ***/
372
373
374 static void
375 master_state_get_prefix_result (void *cls, int64_t result,
376                                 const void *err_msg, uint16_t err_msg_size)
377 {
378   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
379               "master_state_get_prefix:\t%" PRId64 " (%s)\n", result, err_msg);
380   // FIXME: GNUNET_assert (2 == result);
381   slave_state_get_prefix ();
382 }
383
384
385 static void
386 master_state_get_prefix ()
387 {
388   test = TEST_MASTER_STATE_GET_PREFIX;
389   GNUNET_PSYC_channel_state_get_prefix (mst_chn, "_foo", state_get_var,
390                                         master_state_get_prefix_result, NULL);
391 }
392
393
394 /*** Slave state_get() ***/
395
396
397 static void
398 slave_state_get_result (void *cls, int64_t result,
399                         const void *err_msg, uint16_t err_msg_size)
400 {
401   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
402               "slave_state_get:\t%" PRId64 " (%.*s)\n",
403               result, err_msg_size, err_msg);
404   // FIXME: GNUNET_assert (2 == result);
405   master_state_get_prefix ();
406 }
407
408
409 static void
410 slave_state_get ()
411 {
412   test = TEST_SLAVE_STATE_GET;
413   GNUNET_PSYC_channel_state_get (slv_chn, "_foo_bar_baz", state_get_var,
414                                  slave_state_get_result, NULL);
415 }
416
417
418 /*** Master state_get() ***/
419
420
421 static void
422 master_state_get_result (void *cls, int64_t result,
423                          const void *err_msg, uint16_t err_msg_size)
424 {
425   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
426               "master_state_get:\t%" PRId64 " (%.*s)\n",
427               result, err_msg_size, err_msg);
428   // FIXME: GNUNET_assert (1 == result);
429   slave_state_get ();
430 }
431
432
433 static void
434 master_state_get ()
435 {
436   test = TEST_MASTER_STATE_GET;
437   GNUNET_PSYC_channel_state_get (mst_chn, "_foo_bar_baz", state_get_var,
438                                  master_state_get_result, NULL);
439 }
440
441
442 /*** Slave history_replay() ***/
443
444 static void
445 slave_history_replay_result (void *cls, int64_t result,
446                              const void *err_msg, uint16_t err_msg_size)
447 {
448   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
449               "slave_history_replay:\t%" PRId64 " (%.*s)\n",
450               result,
451               (int) err_msg_size,
452               (const char *) err_msg);
453   GNUNET_assert (9 == result);
454
455   master_state_get ();
456 }
457
458
459 static void
460 slave_history_replay ()
461 {
462   test = TEST_SLAVE_HISTORY_REPLAY;
463   GNUNET_PSYC_channel_history_replay (slv_chn, 1, 1, "",
464                                       GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
465                                       slave_message_cb,
466                                       slave_message_part_cb,
467                                       slave_history_replay_result, NULL);
468 }
469
470
471 /*** Master history_replay() ***/
472
473
474 static void
475 master_history_replay_result (void *cls, int64_t result,
476                               const void *err_msg, uint16_t err_msg_size)
477 {
478   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
479               "master_history_replay:\t%" PRId64 " (%.*s)\n",
480               result,
481               (int) err_msg_size,
482               (const char *) err_msg);
483   GNUNET_assert (9 == result);
484
485   slave_history_replay ();
486 }
487
488
489 static void
490 master_history_replay ()
491 {
492   test = TEST_MASTER_HISTORY_REPLAY;
493   GNUNET_PSYC_channel_history_replay (mst_chn, 1, 1, "",
494                                       GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
495                                       master_message_cb,
496                                       master_message_part_cb,
497                                       master_history_replay_result, NULL);
498 }
499
500
501 /*** Slave history_replay_latest() ***/
502
503
504 static void
505 slave_history_replay_latest_result (void *cls, int64_t result,
506                                     const void *err_msg, uint16_t err_msg_size)
507 {
508   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
509               "slave_history_replay_latest:\t%" PRId64 " (%.*s)\n",
510               result,
511               (int) err_msg_size,
512               (const char *) err_msg);
513   GNUNET_assert (9 == result);
514
515   master_history_replay ();
516 }
517
518
519 static void
520 slave_history_replay_latest ()
521 {
522   test = TEST_SLAVE_HISTORY_REPLAY_LATEST;
523   GNUNET_PSYC_channel_history_replay_latest (slv_chn, 1, "",
524                                              GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
525                                              &slave_message_cb,
526                                              &slave_message_part_cb,
527                                              &slave_history_replay_latest_result,
528                                              NULL);
529 }
530
531
532 /*** Master history_replay_latest() ***/
533
534
535 static void
536 master_history_replay_latest_result (void *cls, int64_t result,
537                                      const void *err_msg, uint16_t err_msg_size)
538 {
539   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
540               "master_history_replay_latest:\t%" PRId64 " (%.*s)\n",
541               result, err_msg_size, err_msg);
542   GNUNET_assert (9 == result);
543
544   slave_history_replay_latest ();
545 }
546
547
548 static void
549 master_history_replay_latest ()
550 {
551   test = TEST_MASTER_HISTORY_REPLAY_LATEST;
552   GNUNET_PSYC_channel_history_replay_latest (mst_chn, 1, "",
553                                              GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
554                                              &master_message_cb,
555                                              &master_message_part_cb,
556                                              &master_history_replay_latest_result,
557                                              NULL);
558 }
559
560
561 static void
562 transmit_resume (void *cls)
563 {
564   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
565   struct TransmitClosure *tmit = cls;
566   if (NULL != tmit->mst_tmit)
567     GNUNET_PSYC_master_transmit_resume (tmit->mst_tmit);
568   else
569     GNUNET_PSYC_slave_transmit_resume (tmit->slv_tmit);
570 }
571
572
573 static int
574 tmit_notify_data (void *cls, uint16_t *data_size, void *data)
575 {
576   struct TransmitClosure *tmit = cls;
577   if (0 == tmit->data_count)
578   {
579     *data_size = 0;
580     return GNUNET_YES;
581   }
582
583   uint16_t size = strlen (tmit->data[tmit->n]);
584   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
585               "Test #%d: Transmit notify data: %u bytes available, "
586               "processing fragment %u/%u (size %u).\n",
587               test, *data_size, tmit->n + 1, tmit->data_count, size);
588   if (*data_size < size)
589   {
590     *data_size = 0;
591     GNUNET_assert (0);
592     return GNUNET_SYSERR;
593   }
594
595   if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
596   {
597     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
598                 "Test #%d: Transmission paused.\n", test);
599     tmit->paused = GNUNET_YES;
600     GNUNET_SCHEDULER_add_delayed (
601       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
602                                      tmit->data_delay[tmit->n]),
603       &transmit_resume, tmit);
604     *data_size = 0;
605     return GNUNET_NO;
606   }
607   tmit->paused = GNUNET_NO;
608
609   *data_size = size;
610   memcpy (data, tmit->data[tmit->n], size);
611
612   return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
613 }
614
615
616 static int
617 tmit_notify_mod (void *cls, uint16_t *data_size, void *data, uint8_t *oper,
618                  uint32_t *full_value_size)
619 {
620   struct TransmitClosure *tmit = cls;
621   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
622               "Test #%d: Transmit notify modifier: %lu bytes available, "
623               "%u modifiers left to process.\n",
624               test, *data_size, GNUNET_PSYC_env_get_count (tmit->env));
625
626   uint16_t name_size = 0;
627   size_t value_size = 0;
628   const char *value = NULL;
629
630   if (NULL != oper && NULL != tmit->mod)
631   { /* New modifier */
632     tmit->mod = tmit->mod->next;
633     if (NULL == tmit->mod)
634     { /* No more modifiers, continue with data */
635       *data_size = 0;
636       return GNUNET_YES;
637     }
638
639     GNUNET_assert (tmit->mod->value_size < UINT32_MAX);
640     *full_value_size = tmit->mod->value_size;
641     *oper = tmit->mod->oper;
642     name_size = strlen (tmit->mod->name);
643
644     if (name_size + 1 + tmit->mod->value_size <= *data_size)
645     {
646       *data_size = name_size + 1 + tmit->mod->value_size;
647     }
648     else
649     {
650       tmit->mod_value_size = tmit->mod->value_size;
651       value_size = *data_size - name_size - 1;
652       tmit->mod_value_size -= value_size;
653       tmit->mod_value = tmit->mod->value + value_size;
654     }
655
656     memcpy (data, tmit->mod->name, name_size);
657     ((char *)data)[name_size] = '\0';
658     memcpy ((char *)data + name_size + 1, tmit->mod->value, value_size);
659   }
660   else if (NULL != tmit->mod_value && 0 < tmit->mod_value_size)
661   { /* Modifier continuation */
662     value = tmit->mod_value;
663     if (tmit->mod_value_size <= *data_size)
664     {
665       value_size = tmit->mod_value_size;
666       tmit->mod_value = NULL;
667     }
668     else
669     {
670       value_size = *data_size;
671       tmit->mod_value += value_size;
672     }
673     tmit->mod_value_size -= value_size;
674
675     if (*data_size < value_size)
676     {
677       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
678                   "value larger than buffer: %u < %zu\n",
679                   *data_size, value_size);
680       *data_size = 0;
681       return GNUNET_NO;
682     }
683
684     *data_size = value_size;
685     memcpy (data, value, value_size);
686   }
687
688   return GNUNET_NO;
689 }
690
691
692 static void
693 slave_join ();
694
695
696 static void
697 slave_transmit ()
698 {
699   test = TEST_SLAVE_TRANSMIT;
700   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
701               "Test #%d: Slave sending request to master.\n", test);
702
703   tmit = GNUNET_new (struct TransmitClosure);
704   tmit->env = GNUNET_PSYC_env_create ();
705   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
706                               "_abc", "abc def", 7);
707   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
708                               "_abc_def", "abc def ghi", 11);
709   tmit->mod = GNUNET_PSYC_env_head (tmit->env);
710   tmit->n = 0;
711   tmit->data[0] = "slave test";
712   tmit->data_count = 1;
713   tmit->slv_tmit
714     = GNUNET_PSYC_slave_transmit (slv, "_request_test", &tmit_notify_mod,
715                                   &tmit_notify_data, tmit,
716                                   GNUNET_PSYC_SLAVE_TRANSMIT_NONE);
717 }
718
719
720 static void
721 slave_remove_cb (void *cls, int64_t result,
722                  const void *err_msg, uint16_t err_msg_size)
723 {
724   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
725               "slave_remove:\t%" PRId64 " (%.*s)\n",
726               result, err_msg_size, err_msg);
727
728   slave_transmit ();
729 }
730
731
732 static void
733 slave_remove ()
734 {
735   test = TEST_SLAVE_REMOVE;
736   struct GNUNET_PSYC_Channel *chn = GNUNET_PSYC_master_get_channel (mst);
737   GNUNET_PSYC_channel_slave_remove (chn, &slave_pub_key, 2,
738                                     &slave_remove_cb, chn);
739 }
740
741
742 static void
743 slave_add_cb (void *cls, int64_t result,
744               const void *err_msg, uint16_t err_msg_size)
745 {
746   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
747               "slave_add:\t%" PRId64 " (%.*s)\n",
748               result, err_msg_size, err_msg);
749   slave_remove ();
750 }
751
752
753 static void
754 slave_add ()
755 {
756   test = TEST_SLAVE_ADD;
757   struct GNUNET_PSYC_Channel *chn = GNUNET_PSYC_master_get_channel (mst);
758   GNUNET_PSYC_channel_slave_add (chn, &slave_pub_key, 2, 2, &slave_add_cb, chn);
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   slave_join (TEST_SLAVE_JOIN_ACCEPT);
767 }
768
769
770 static void
771 schedule_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_WARNING,
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_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_WARNING,
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_WARNING,
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_WARNING, "Test #%d: Joining slave.\n");
841
842   struct GNUNET_PeerIdentity origin = this_peer;
843   struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
844   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN,
845                               "_foo", "bar baz", 7);
846   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN,
847                               "_foo_bar", "foo bar baz", 11);
848   struct GNUNET_PSYC_Message *
849     join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 9);
850
851   slv = GNUNET_PSYC_slave_join (cfg, &channel_pub_key, slave_key,
852                                 GNUNET_PSYC_SLAVE_JOIN_NONE,
853                                 &origin, 0, NULL,
854                                 &slave_message_cb, &slave_message_part_cb,
855                                 &slave_connect_cb, &join_decision_cb, NULL,
856                                 join_msg);
857   GNUNET_free (join_msg);
858   slv_chn = GNUNET_PSYC_slave_get_channel (slv);
859   GNUNET_PSYC_env_destroy (env);
860 }
861
862
863 static void
864 master_transmit ()
865 {
866   test = TEST_MASTER_TRANSMIT;
867   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
868               "Test #%d: Master sending message to all.\n", test);
869   end_count = 0;
870
871   uint32_t i, j;
872
873   char *name_max = "_test_max";
874   uint8_t name_max_size = sizeof ("_test_max");
875   char *val_max = GNUNET_malloc (GNUNET_PSYC_MODIFIER_MAX_PAYLOAD);
876   for (i = 0; i < GNUNET_PSYC_MODIFIER_MAX_PAYLOAD; i++)
877     val_max[i] = (0 == i % 10000) ? '0' + i / 10000 : '.';
878
879   char *name_cont = "_test_cont";
880   uint8_t name_cont_size = sizeof ("_test_cont");
881   char *val_cont = GNUNET_malloc (GNUNET_PSYC_MODIFIER_MAX_PAYLOAD
882                                   + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD);
883   for (i = 0; i < GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size; i++)
884     val_cont[i] = (0 == i % 10000) ? '0' + i / 10000 : ':';
885   for (j = 0; j < GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD; j++, i++)
886     val_cont[i] = (0 == j % 10000) ? '0' + j / 10000 : '!';
887
888   tmit = GNUNET_new (struct TransmitClosure);
889   tmit->env = GNUNET_PSYC_env_create ();
890   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
891                               "_foo", "bar baz", 7);
892   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
893                               name_max, val_max,
894                               GNUNET_PSYC_MODIFIER_MAX_PAYLOAD
895                               - name_max_size);
896   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
897                               "_foo_bar", "foo bar baz", 11);
898   GNUNET_PSYC_env_add (tmit->env, GNUNET_PSYC_OP_ASSIGN,
899                               name_cont, val_cont,
900                               GNUNET_PSYC_MODIFIER_MAX_PAYLOAD - name_cont_size
901                               + GNUNET_PSYC_MOD_CONT_MAX_PAYLOAD);
902   tmit->mod = GNUNET_PSYC_env_head (tmit->env);
903   tmit->data[0] = "foo";
904   tmit->data[1] =  GNUNET_malloc (GNUNET_PSYC_DATA_MAX_PAYLOAD + 1);
905   for (i = 0; i < GNUNET_PSYC_DATA_MAX_PAYLOAD; i++)
906     tmit->data[1][i] = (0 == i % 10000) ? '0' + i / 10000 : '_';
907   tmit->data[2] = "foo bar";
908   tmit->data[3] = "foo bar baz";
909   tmit->data_delay[1] = 3;
910   tmit->data_count = 4;
911   tmit->mst_tmit
912     = GNUNET_PSYC_master_transmit (mst, "_notice_test", &tmit_notify_mod,
913                                    &tmit_notify_data, tmit,
914                                    GNUNET_PSYC_MASTER_TRANSMIT_INC_GROUP_GEN);
915 }
916
917
918 static void
919 master_start_cb (void *cls, int result, uint64_t max_message_id)
920 {
921   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922               "Test #%d: Master started: %d, max_message_id: %" PRIu64 "\n",
923               test, result, max_message_id);
924   GNUNET_assert (TEST_MASTER_START == test);
925   GNUNET_assert (GNUNET_OK == result || GNUNET_NO == result);
926   slave_join (TEST_SLAVE_JOIN_REJECT);
927 }
928
929
930 static void
931 master_start ()
932 {
933   test = TEST_MASTER_START;
934   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test #%d: Starting master.\n", test);
935   mst = GNUNET_PSYC_master_start (cfg, channel_key, GNUNET_PSYC_CHANNEL_PRIVATE,
936                                   &master_start_cb, &join_request_cb,
937                                   &master_message_cb, &master_message_part_cb,
938                                   NULL);
939   mst_chn = GNUNET_PSYC_master_get_channel (mst);
940 }
941
942
943 static void
944 schedule_master_start (void *cls)
945 {
946   master_start ();
947 }
948
949
950 static void
951 core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
952 {
953   this_peer = *my_identity;
954
955 #if DEBUG_TEST_PSYC
956   master_start ();
957 #else
958   /* Allow some time for the services to initialize. */
959   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
960                                 &schedule_master_start, NULL);
961 #endif
962
963 }
964
965 /**
966  * Main function of the test, run from scheduler.
967  *
968  * @param cls NULL
969  * @param cfg configuration we use (also to connect to PSYC service)
970  * @param peer handle to access more of the peer (not used)
971  */
972 static void
973 #if DEBUG_TEST_PSYC
974 run (void *cls, char *const *args, const char *cfgfile,
975      const struct GNUNET_CONFIGURATION_Handle *c)
976 #else
977 run (void *cls,
978      const struct GNUNET_CONFIGURATION_Handle *c,
979      struct GNUNET_TESTING_Peer *peer)
980 #endif
981 {
982   cfg = c;
983   end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
984
985   channel_key = GNUNET_CRYPTO_eddsa_key_create ();
986   slave_key = GNUNET_CRYPTO_ecdsa_key_create ();
987
988   GNUNET_CRYPTO_eddsa_key_get_public (channel_key, &channel_pub_key);
989   GNUNET_CRYPTO_ecdsa_key_get_public (slave_key, &slave_pub_key);
990
991   core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
992                               NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
993 }
994
995
996 int
997 main (int argc, char *argv[])
998 {
999   res = 1;
1000 #if DEBUG_TEST_PSYC
1001   const struct GNUNET_GETOPT_CommandLineOption opts[] = {
1002     GNUNET_GETOPT_OPTION_END
1003   };
1004   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-psyc",
1005                                        "test-psyc [options]",
1006                                        opts, &run, NULL))
1007     return 1;
1008 #else
1009   if (0 != GNUNET_TESTING_peer_run ("test-psyc", "test_psyc.conf", &run, NULL))
1010     return 1;
1011 #endif
1012   return res;
1013 }
1014
1015 /* end of test_psyc.c */