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