-preparations for replacement of try_connect call
[oweals/gnunet.git] / src / social / test_social.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  * @file social/test_social.c
22  * @brief Tests for the Social API.
23  * @author Gabor X Toth
24  */
25
26 #include <inttypes.h>
27
28 #include "platform.h"
29 #include "gnunet_crypto_lib.h"
30 #include "gnunet_common.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_testing_lib.h"
33 #include "gnunet_env_lib.h"
34 #include "gnunet_psyc_util_lib.h"
35 #include "gnunet_social_service.h"
36 #include "gnunet_core_service.h"
37 #include "gnunet_identity_service.h"
38
39 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
40
41 #define DATA2ARG(data) data, sizeof (data)
42
43 /**
44  * Return value from 'main'.
45  */
46 int res;
47
48 /**
49  * Handle for task for timeout termination.
50  */
51 struct GNUNET_SCHEDULER_Task * end_badly_task;
52
53 const struct GNUNET_CONFIGURATION_Handle *cfg;
54
55 struct GNUNET_CORE_Handle *core;
56 struct GNUNET_PeerIdentity this_peer;
57
58 struct GNUNET_IDENTITY_Handle *id;
59
60 const struct GNUNET_IDENTITY_Ego *host_ego;
61 const struct GNUNET_IDENTITY_Ego *guest_ego;
62
63 const char *host_name = "Host One";
64 const char *guest_name = "Guest One";
65
66 struct GNUNET_CRYPTO_EddsaPrivateKey *place_key;
67 struct GNUNET_CRYPTO_EcdsaPrivateKey *guest_key;
68
69 struct GNUNET_CRYPTO_EddsaPublicKey place_pub_key;
70 struct GNUNET_CRYPTO_EcdsaPublicKey guest_pub_key;
71 struct GNUNET_CRYPTO_EcdsaPublicKey host_pub_key;
72
73 struct GNUNET_SOCIAL_Slicer *host_slicer;
74 struct GNUNET_SOCIAL_Slicer *guest_slicer;
75
76 struct GNUNET_SOCIAL_Host *hst;
77 struct GNUNET_SOCIAL_Guest *gst;
78
79 struct GNUNET_SOCIAL_Place *hst_plc;
80 struct GNUNET_SOCIAL_Place *gst_plc;
81
82 struct GNUNET_SOCIAL_Nym *nym_eject;
83
84 struct GuestEnterMessage
85 {
86   struct GNUNET_PSYC_Message *msg;
87   const char *method_name;
88   struct GNUNET_ENV_Environment *env;
89   void *data;
90   uint16_t data_size;
91 } guest_enter_msg;
92
93 struct TransmitClosure
94 {
95   struct GNUNET_SOCIAL_Announcement *host_ann;
96   struct GNUNET_SOCIAL_TalkRequest *guest_talk;
97   struct GNUNET_ENV_Environment *env;
98   char *data[16];
99   uint8_t data_delay[16];
100   uint8_t data_count;
101   uint8_t paused;
102   uint8_t n;
103 } tmit;
104
105 struct ResultClosure {
106   uint32_t n;
107 } mod_foo_bar_rcls;
108
109 uint8_t join_req_count;
110 struct GNUNET_PSYC_Message *join_resp;
111
112 uint32_t counter;
113
114 uint8_t guest_pkey_added = GNUNET_NO;
115
116 enum
117 {
118   TEST_NONE = 0,
119   TEST_HOST_ANSWER_DOOR_REFUSE      =  1,
120   TEST_GUEST_RECV_ENTRY_DCSN_REFUSE =  2,
121   TEST_HOST_ANSWER_DOOR_ADMIT       =  3,
122   TEST_GUEST_RECV_ENTRY_DCSN_ADMIT  =  4,
123   TEST_HOST_ANNOUNCE                =  5,
124   TEST_HOST_ANNOUNCE_END            =  6,
125   TEST_HOST_ANNOUNCE2               =  7,
126   TEST_HOST_ANNOUNCE2_END           =  8,
127   TEST_GUEST_TALK                   =  9,
128   TEST_GUEST_HISTORY_REPLAY         = 10,
129   TEST_GUEST_HISTORY_REPLAY_LATEST  = 11,
130   TEST_GUEST_LOOK_AT                = 12,
131   TEST_GUEST_LOOK_FOR               = 13,
132   TEST_GUEST_LEAVE                  = 14,
133   TEST_HOST_ADVERTISE               = 15,
134   TEST_GUEST_ENTER_BY_NAME          = 16,
135   TEST_HOST_LEAVE                   = 17,
136 } test;
137
138
139 static void
140 guest_enter ();
141
142 static void
143 guest_enter_by_name ();
144
145 static void
146 guest_talk ();
147
148 static void
149 host_announce2 ();
150
151
152 /**
153  * Clean up all resources used.
154  */
155 static void
156 cleanup ()
157 {
158   if (NULL != core)
159   {
160     GNUNET_CORE_disconnect (core);
161     core = NULL;
162   }
163
164   if (NULL != id)
165   {
166     GNUNET_IDENTITY_disconnect (id);
167     id = NULL;
168   }
169
170   if (NULL != gst)
171   {
172     GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, NULL, NULL, NULL);
173     gst = NULL;
174     gst_plc = NULL;
175   }
176   if (NULL != hst)
177   {
178     GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, NULL, NULL);
179     hst = NULL;
180     hst_plc = NULL;
181   }
182   GNUNET_SCHEDULER_shutdown ();
183 }
184
185
186 /**
187  * Terminate the test case (failure).
188  *
189  * @param cls NULL
190  * @param tc scheduler context
191  */
192 static void
193 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
194 {
195   res = 1;
196   cleanup ();
197   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test FAILED.\n");
198 }
199
200
201 /**
202  * Terminate the test case (success).
203  *
204  * @param cls NULL
205  * @param tc scheduler context
206  */
207 static void
208 end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
209 {
210   res = 0;
211   cleanup ();
212   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Test PASSED.\n");
213 }
214
215
216 /**
217  * Finish the test case (successfully).
218  */
219 static void
220 end ()
221 {
222   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ending tests.\n");
223
224   if (end_badly_task != NULL)
225   {
226     GNUNET_SCHEDULER_cancel (end_badly_task);
227     end_badly_task = NULL;
228   }
229   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
230                                 &end_normally, NULL);
231 }
232
233
234 static void
235 transmit_resume (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
236 {
237   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission resumed.\n");
238   struct TransmitClosure *tmit = cls;
239   if (NULL != tmit->host_ann)
240     GNUNET_SOCIAL_host_announce_resume (tmit->host_ann);
241   else
242     GNUNET_SOCIAL_guest_talk_resume (tmit->guest_talk);
243 }
244
245
246 static int
247 notify_data (void *cls, uint16_t *data_size, void *data)
248 {
249   struct TransmitClosure *tmit = cls;
250   if (NULL != tmit->env)
251   {
252     GNUNET_ENV_environment_destroy (tmit->env);
253     tmit->env = NULL;
254   }
255   if (0 == tmit->data_count)
256   {
257     *data_size = 0;
258     return GNUNET_YES;
259   }
260
261   uint16_t size = strlen (tmit->data[tmit->n]) + 1;
262   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
263               "Transmit notify data: %u bytes available, "
264               "processing fragment %u/%u (size %u).\n",
265               *data_size, tmit->n + 1, tmit->data_count, size);
266   if (*data_size < size)
267   {
268     *data_size = 0;
269     GNUNET_assert (0);
270     return GNUNET_SYSERR;
271   }
272
273   if (GNUNET_YES != tmit->paused && 0 < tmit->data_delay[tmit->n])
274   {
275     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmission paused.\n");
276     tmit->paused = GNUNET_YES;
277     GNUNET_SCHEDULER_add_delayed (
278       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
279                                      tmit->data_delay[tmit->n]),
280       &transmit_resume, tmit);
281     *data_size = 0;
282     return GNUNET_NO;
283   }
284   tmit->paused = GNUNET_NO;
285
286   *data_size = size;
287   memcpy (data, tmit->data[tmit->n], size);
288
289   return ++tmit->n < tmit->data_count ? GNUNET_NO : GNUNET_YES;
290 }
291
292
293 static void
294 host_left ()
295 {
296   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
297               "The host has left the place.\n");
298   GNUNET_SOCIAL_slicer_destroy (host_slicer);
299   host_slicer = NULL;
300   hst = NULL;
301   hst_plc = NULL;
302
303   end ();
304 }
305
306
307 static void
308 schedule_host_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
309 {
310   test = TEST_HOST_LEAVE;
311   GNUNET_SOCIAL_host_leave (hst, GNUNET_NO, &host_left, NULL);
312 }
313
314
315 static void
316 id_guest_ego_cb2 (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
317 {
318   GNUNET_assert (NULL != ego);
319   guest_ego = ego;
320
321   guest_enter_by_name ();
322 }
323
324
325 static void
326 host_recv_advertise_result (void *cls, int32_t success, const char *emsg)
327 {
328   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
329               "Test #%u: Advertise result: %d (%s).\n",
330               test, success, emsg);
331   GNUNET_assert (GNUNET_YES == success);
332
333   GNUNET_assert (GNUNET_YES == guest_pkey_added);
334   GNUNET_IDENTITY_ego_lookup (cfg, guest_name, id_guest_ego_cb2, NULL);
335 }
336
337
338 static void
339 host_advertise ()
340 {
341   test = TEST_HOST_ADVERTISE;
342   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
343               "Test #%u: Advertising place.\n", test);
344
345   GNUNET_SOCIAL_host_advertise (hst, "home", 1, &this_peer,
346                                 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES),
347                                 "let.me*in!", host_recv_advertise_result, hst);
348 }
349
350
351 static void
352 host_farewell (void *cls,
353                const struct GNUNET_SOCIAL_Nym *nym,
354                struct GNUNET_ENV_Environment *env)
355 {
356   const struct GNUNET_CRYPTO_EcdsaPublicKey *
357     nym_key = GNUNET_SOCIAL_nym_get_key (nym);
358
359   char *str = GNUNET_CRYPTO_ecdsa_public_key_to_string (nym_key);
360   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
361               "Farewell: nym %s (%s) has left the place.\n",
362               GNUNET_h2s (GNUNET_SOCIAL_nym_get_key_hash (nym)), str);
363   GNUNET_free (str);
364   GNUNET_assert (1 == GNUNET_ENV_environment_get_count (env));
365   if (0 != memcmp (&guest_pub_key, nym_key, sizeof (*nym_key)))
366   {
367     str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&guest_pub_key);
368     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
369                 "Farewell: nym does not match guest: %s\n", str);
370     GNUNET_free (str);
371     GNUNET_assert (0);
372   }
373   host_advertise ();
374 }
375
376
377 static void
378 guest_left (void *cls)
379 {
380   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
381               "The guest has left the place.\n");
382   GNUNET_SOCIAL_slicer_destroy (guest_slicer);
383   guest_slicer = NULL;
384   gst = NULL;
385   gst_plc = NULL;
386 }
387
388
389 static void
390 guest_leave()
391 {
392   test = TEST_GUEST_LEAVE;
393
394   struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
395   GNUNET_ENV_environment_add (env, GNUNET_ENV_OP_SET,
396                               "_message", DATA2ARG ("Leaving."));
397   GNUNET_SOCIAL_guest_leave (gst, GNUNET_NO, env, &guest_left, NULL);
398   GNUNET_ENV_environment_destroy (env);
399
400   /* @todo test keep_active */
401 }
402
403
404 static void
405 schedule_guest_leave (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
406 {
407   guest_leave ();
408 }
409
410
411 static void
412 guest_look_for_result (void *cls, int64_t result_code,
413                       const void *data, uint16_t data_size)
414 {
415   struct ResultClosure *rcls = cls;
416   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
417               "guest_look_for_result: %d\n", result_code);
418   GNUNET_assert (GNUNET_OK == result_code);
419   GNUNET_assert (3 == rcls->n);
420   GNUNET_free (rcls);
421   GNUNET_SCHEDULER_add_now (&schedule_guest_leave, NULL);
422 }
423
424
425 static void
426 guest_look_for_var (void *cls,
427                    const struct GNUNET_MessageHeader *mod,
428                    const char *name,
429                    const void *value,
430                    uint32_t value_size,
431                    uint32_t full_value_size)
432 {
433   struct ResultClosure *rcls = cls;
434   rcls->n++;
435   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
436               "guest_look_for_var: %s\n%.*s\n",
437               name, value_size, value);
438 }
439
440
441 static void
442 guest_look_for ()
443 {
444   test = TEST_GUEST_LOOK_FOR;
445   struct ResultClosure *rcls = GNUNET_malloc (sizeof (*rcls));
446   GNUNET_SOCIAL_place_look_for (gst_plc, "_foo", guest_look_for_var, guest_look_for_result, rcls);
447 }
448
449
450 static void
451 guest_look_at_result (void *cls, int64_t result_code,
452                       const void *data, uint16_t data_size)
453 {
454   struct ResultClosure *rcls = cls;
455
456   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
457               "guest_look_at_result: %d\n", result_code);
458   GNUNET_assert (GNUNET_OK == result_code);
459   GNUNET_assert (1 == rcls->n);
460   GNUNET_free (rcls);
461   guest_look_for ();
462 }
463
464
465 static void
466 guest_look_at_var (void *cls,
467                    const struct GNUNET_MessageHeader *mod,
468                    const char *name,
469                    const void *value,
470                    uint32_t value_size,
471                    uint32_t full_value_size)
472 {
473   struct ResultClosure *rcls = cls;
474   rcls->n++;
475
476   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
477               "guest_look_at_var: %s\n%.*s\n",
478               name, value_size, value);
479 }
480
481
482 static void
483 guest_look_at ()
484 {
485   test = TEST_GUEST_LOOK_AT;
486   struct ResultClosure *rcls = GNUNET_malloc (sizeof (*rcls));
487   GNUNET_SOCIAL_place_look_at (gst_plc, "_foo_bar", guest_look_at_var, guest_look_at_result, rcls);
488 }
489
490
491 static void
492 guest_recv_history_replay_latest_result (void *cls, int64_t result,
493                                          const void *data, uint16_t data_size)
494 {
495   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
496               "Test #%u: Guest received latest history replay result: %" PRId64 "\n"
497               "%.*s\n",
498               test, result, data_size, data);
499   GNUNET_assert (2 == counter); /* message count */
500   GNUNET_assert (7 == result); /* fragment count */
501
502   guest_look_at ();
503 }
504
505
506 static void
507 guest_history_replay_latest ()
508 {
509   test = TEST_GUEST_HISTORY_REPLAY_LATEST;
510   counter = 0;
511   GNUNET_SOCIAL_place_history_replay_latest (gst_plc, 3, "",
512                                              GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
513                                              guest_slicer,
514                                              &guest_recv_history_replay_latest_result,
515                                              NULL);
516 }
517
518
519 static void
520 guest_recv_history_replay_result (void *cls, int64_t result,
521                                   const void *data, uint16_t data_size)
522 {
523   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
524               "Test #%u: Guest received history replay result: %" PRId64 "\n"
525               "%.*s\n",
526               test, result, data_size, data);
527   GNUNET_assert (2 == counter); /* message count */
528   GNUNET_assert (7 == result); /* fragment count */
529
530   guest_history_replay_latest ();
531 }
532
533
534 static void
535 guest_history_replay ()
536 {
537   test = TEST_GUEST_HISTORY_REPLAY;
538   counter = 0;
539   GNUNET_SOCIAL_place_history_replay (gst_plc, 1, 3, "",
540                                       GNUNET_PSYC_HISTORY_REPLAY_LOCAL,
541                                       guest_slicer,
542                                       &guest_recv_history_replay_result,
543                                       NULL);
544 }
545
546
547 static void
548 guest_recv_method (void *cls,
549                   const struct GNUNET_PSYC_MessageMethod *meth,
550                   uint64_t message_id,
551                   uint32_t flags,
552                   const struct GNUNET_SOCIAL_Nym *nym,
553                   const char *method_name)
554 {
555   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
556               "Test #%u: Guest received method for message ID %" PRIu64 ":\n"
557               "%s (flags: %x)\n",
558               test, message_id, method_name, flags);
559   /** @todo FIXME: check message */
560 }
561
562
563 static void
564 guest_recv_modifier (void *cls,
565                      const struct GNUNET_MessageHeader *msg,
566                      uint64_t message_id,
567                      enum GNUNET_ENV_Operator oper,
568                      const char *name,
569                      const void *value,
570                      uint16_t value_size,
571                      uint16_t full_value_size)
572 {
573   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
574               "Test #%u: Guest received modifier for message ID %" PRIu64 ":\n"
575               "%c%s: %.*s (size: %u)\n",
576               test, message_id, oper, name, value_size, value, value_size);
577   /** @todo FIXME: check modifier */
578 }
579
580 static void
581 guest_recv_mod_foo_bar (void *cls,
582                         const struct GNUNET_MessageHeader *msg,
583                         uint64_t message_id,
584                         enum GNUNET_ENV_Operator oper,
585                         const char *name,
586                         const void *value,
587                         uint16_t value_size,
588                         uint16_t full_value_size)
589 {
590   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
591               "Test #%u: Guest received modifier matching _foo_bar for message ID %" PRIu64 ":\n"
592               "%c%s: %.*s (size: %u)\n",
593               test, message_id, oper, name, value_size, value, value_size);
594   struct ResultClosure *rc = cls;
595   rc->n++;
596   /** @todo FIXME: check modifier */
597 }
598
599
600 static void
601 guest_recv_data (void *cls,
602                 const struct GNUNET_MessageHeader *msg,
603                 uint64_t message_id,
604                 uint64_t data_offset,
605                 const void *data,
606                 uint16_t data_size)
607 {
608   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
609               "Test #%u: Guest received data for message ID %" PRIu64 ":\n"
610               "%.*s\n",
611               test, message_id, data_size, data);
612   /** @todo FIXME: check data */
613 }
614
615
616 static void
617 guest_recv_eom (void *cls,
618                const struct GNUNET_MessageHeader *msg,
619                uint64_t message_id,
620                uint8_t cancelled)
621 {
622   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
623               "Test #%u: Guest received end of message ID %" PRIu64
624               ", cancelled: %u\n",
625               test, message_id, cancelled);
626
627   switch (test)
628   {
629   case TEST_HOST_ANNOUNCE:
630     test = TEST_HOST_ANNOUNCE_END;
631     break;
632
633   case TEST_HOST_ANNOUNCE_END:
634     host_announce2 ();
635     break;
636
637   case TEST_HOST_ANNOUNCE2:
638     test = TEST_HOST_ANNOUNCE2_END;
639     break;
640
641   case TEST_HOST_ANNOUNCE2_END:
642     guest_talk ();
643     break;
644
645   case TEST_GUEST_HISTORY_REPLAY:
646   case TEST_GUEST_HISTORY_REPLAY_LATEST:
647     counter++;
648     break;
649
650   default:
651     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "invalid test: %d\n", test);
652     GNUNET_assert (0);
653   }
654 }
655
656
657 static void
658 host_recv_method (void *cls,
659                   const struct GNUNET_PSYC_MessageMethod *meth,
660                   uint64_t message_id,
661                   uint32_t flags,
662                   const struct GNUNET_SOCIAL_Nym *nym,
663                   const char *method_name)
664 {
665   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
666               "Test #%u: Host received method for message ID %" PRIu64 ":\n"
667               "%s\n",
668               test, message_id, method_name);
669   /** @todo FIXME: check message */
670 }
671
672
673 static void
674 host_recv_modifier (void *cls,
675                     const struct GNUNET_MessageHeader *msg,
676                     uint64_t message_id,
677                     enum GNUNET_ENV_Operator oper,
678                     const char *name,
679                     const void *value,
680                     uint16_t value_size,
681                     uint16_t full_value_size)
682 {
683   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
684               "Test #%u: Host received modifier for message ID %" PRIu64 ":\n"
685               "%c%s: %.*s\n",
686               test, message_id, oper, name, value_size, value);
687 }
688
689
690 static void
691 host_recv_data (void *cls,
692                 const struct GNUNET_MessageHeader *msg,
693                 uint64_t message_id,
694                 uint64_t data_offset,
695                 const void *data,
696                 uint16_t data_size)
697 {
698   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
699               "Test #%u: Host received data for message ID %" PRIu64 ":\n"
700               "%.*s\n",
701               test, message_id, data_size, data);
702 }
703
704
705 static void
706 host_recv_eom (void *cls,
707                const struct GNUNET_MessageHeader *msg,
708                uint64_t message_id,
709                uint8_t cancelled)
710 {
711   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
712               "Test #%u: Host received end of message ID %" PRIu64
713               ", cancelled: %u\n",
714               test, message_id, cancelled);
715
716   switch (test)
717   {
718   case TEST_HOST_ANNOUNCE:
719     test = TEST_HOST_ANNOUNCE_END;
720     break;
721
722   case TEST_HOST_ANNOUNCE_END:
723     host_announce2 ();
724     break;
725
726   case TEST_HOST_ANNOUNCE2:
727     test = TEST_HOST_ANNOUNCE2_END;
728     break;
729
730   case TEST_HOST_ANNOUNCE2_END:
731     guest_talk ();
732     break;
733
734   case TEST_GUEST_TALK:
735     guest_history_replay ();
736     break;
737
738   default:
739     if (TEST_GUEST_LEAVE <= test)
740       break;
741     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "invalid test: %d\n", test);
742     GNUNET_assert (0);
743   }
744 }
745
746
747 static void
748 guest_talk ()
749 {
750   test = TEST_GUEST_TALK;
751
752   tmit = (struct TransmitClosure) {};
753   tmit.env = GNUNET_ENV_environment_create ();
754   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
755                               "_bar_foo", DATA2ARG ("one two three"));
756   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
757                               "_bar_baz", DATA2ARG ("four five"));
758   tmit.data[0] = "zzz xxx yyy";
759   tmit.data[1] = "zyx wvu tsr qpo";
760   tmit.data_delay[1] = 1;
761   tmit.data[2] = "testing ten nine eight";
762   tmit.data_count = 3;
763
764   tmit.guest_talk
765     = GNUNET_SOCIAL_guest_talk (gst, "_message_guest", tmit.env,
766                                 &notify_data, &tmit,
767                                 GNUNET_SOCIAL_TALK_NONE);
768 }
769
770
771 static void
772 host_announce ()
773 {
774   test = TEST_HOST_ANNOUNCE;
775
776   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
777               "Test #%u: Host announcement.\n", test);
778
779   tmit = (struct TransmitClosure) {};
780   tmit.env = GNUNET_ENV_environment_create ();
781   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
782                               "_foo", DATA2ARG ("bar baz"));
783   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
784                               "_foo_bar", DATA2ARG ("foo bar"));
785   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
786                               "_foo_bar_baz", DATA2ARG ("foo bar baz"));
787   tmit.data[0] = "aaa bbb ccc";
788   tmit.data[1] = "abc def ghi jkl";
789   tmit.data_delay[1] = 1;
790   tmit.data[2] = "testing one two three";
791   tmit.data[3] = "four five";
792   tmit.data_count = 4;
793
794   tmit.host_ann
795     = GNUNET_SOCIAL_host_announce (hst, "_message_host", tmit.env,
796                                    &notify_data, &tmit,
797                                    GNUNET_SOCIAL_ANNOUNCE_NONE);
798 }
799
800
801 static void
802 host_announce2 ()
803 {
804   GNUNET_assert (2 == mod_foo_bar_rcls.n);
805   GNUNET_SOCIAL_slicer_modifier_remove (guest_slicer, "_foo_bar",
806                                         guest_recv_mod_foo_bar);
807
808   test = TEST_HOST_ANNOUNCE2;
809
810   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
811               "Test #%u: Host announcement 2.\n", test);
812
813   tmit = (struct TransmitClosure) {};
814   tmit.env = GNUNET_ENV_environment_create ();
815   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
816                               "_foo2", DATA2ARG ("BAR BAZ"));
817   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
818                               "_foo2_bar", DATA2ARG ("FOO BAR"));
819   GNUNET_ENV_environment_add (tmit.env, GNUNET_ENV_OP_ASSIGN,
820                               "_foo2_bar", DATA2ARG ("FOO BAR BAZ"));
821   tmit.data[0] = "AAA BBB CCC";
822   tmit.data[1] = "ABC DEF GHI JKL";
823   tmit.data[2] = "TESTING ONE TWO THREE";
824   tmit.data_count = 3;
825
826   tmit.host_ann
827     = GNUNET_SOCIAL_host_announce (hst, "_message_host_two", tmit.env,
828                                    &notify_data, &tmit,
829                                    GNUNET_SOCIAL_ANNOUNCE_NONE);
830 }
831
832
833 static void
834 guest_recv_entry_decision (void *cls,
835                            int is_admitted,
836                            const struct GNUNET_PSYC_Message *entry_msg)
837 {
838   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
839               "Test #%u: Guest received entry decision (try %u): %d.\n",
840               test, join_req_count, is_admitted);
841
842   if (NULL != entry_msg)
843   {
844     struct GNUNET_ENV_Environment *env = GNUNET_ENV_environment_create ();
845     const char *method_name = NULL;
846     const void *data = NULL;
847     uint16_t data_size = 0;
848     struct GNUNET_PSYC_MessageHeader *
849       pmsg = GNUNET_PSYC_message_header_create_from_psyc (entry_msg);
850     GNUNET_PSYC_message_parse (pmsg, &method_name, env, &data, &data_size);
851     GNUNET_free (pmsg);
852
853     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
854                 "%s\n%.*s\n",
855                 method_name, data_size, data);
856     /** @todo FIXME: check response message */
857   }
858
859   switch (test)
860   {
861   case TEST_GUEST_RECV_ENTRY_DCSN_REFUSE:
862     GNUNET_assert (GNUNET_NO == is_admitted);
863     guest_enter ();
864     break;
865
866   case TEST_GUEST_RECV_ENTRY_DCSN_ADMIT:
867     GNUNET_assert (GNUNET_YES == is_admitted);
868     host_announce ();
869     break;
870
871   case TEST_GUEST_ENTER_BY_NAME:
872     GNUNET_SCHEDULER_add_now (schedule_host_leave, NULL);
873     break;
874
875   default:
876     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "invalid test: %d\n", test);
877     GNUNET_assert (0);
878   }
879 }
880
881
882 static void
883 host_answer_door (void *cls,
884                   struct GNUNET_SOCIAL_Nym *nym,
885                   const char *method_name,
886                   struct GNUNET_ENV_Environment *env,
887                   size_t data_size,
888                   const void *data)
889 {
890   join_req_count++;
891
892   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
893               "Test #%u: Host received entry request from guest (try %u).\n",
894               test, join_req_count);
895   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
896               "%s\n%.*s\n",
897               method_name, data_size, data);
898
899   switch (test)
900   {
901   case TEST_HOST_ANSWER_DOOR_REFUSE:
902     test = TEST_GUEST_RECV_ENTRY_DCSN_REFUSE;
903     join_resp = GNUNET_PSYC_message_create ("_refuse_nym", env,
904                                             DATA2ARG ("Go away!"));
905     GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_NO, join_resp);
906     break;
907
908   case TEST_HOST_ANSWER_DOOR_ADMIT:
909     test = TEST_GUEST_RECV_ENTRY_DCSN_ADMIT;
910   case TEST_GUEST_ENTER_BY_NAME:
911     join_resp = GNUNET_PSYC_message_create ("_admit_nym", env,
912                                             DATA2ARG ("Welcome, nym!"));
913     GNUNET_SOCIAL_host_entry_decision (hst, nym, GNUNET_YES, join_resp);
914     break;
915
916   default:
917     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "invalid test: %d\n", test);
918     GNUNET_assert (0);
919   }
920 }
921
922
923 static void
924 guest_recv_local_enter (void *cls, int result, uint64_t max_message_id)
925 {
926   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
927               "Test #%u: Guest entered to local place: %d\n",
928               test, result);
929   GNUNET_assert (0 <= result);
930 }
931
932
933 static void
934 guest_enter ()
935 {
936   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
937               "Test #%u: Entering to place as guest.\n", test);
938
939   struct GuestEnterMessage *emsg = &guest_enter_msg;
940
941   emsg->method_name = "_request_enter";
942   emsg->env = GNUNET_ENV_environment_create ();
943   GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
944                               "_abc", "abc def", 7);
945   GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
946                               "_abc_def", "abc def ghi", 11);
947   emsg->data = "let me in";
948   emsg->data_size = strlen (emsg->data) + 1;
949   emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env,
950                                           emsg->data, emsg->data_size);
951
952   gst = GNUNET_SOCIAL_guest_enter (cfg, guest_ego, &place_pub_key,
953                                    &this_peer, 0, NULL, emsg->msg, guest_slicer,
954                                    guest_recv_local_enter,
955                                    guest_recv_entry_decision, NULL);
956   gst_plc = GNUNET_SOCIAL_guest_get_place (gst);
957 }
958
959
960 static void
961 guest_enter_by_name ()
962 {
963   test = TEST_GUEST_ENTER_BY_NAME;
964   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
965               "Test #%u: Entering to place by name as guest.\n", test);
966
967   struct GuestEnterMessage *emsg = &guest_enter_msg;
968
969   emsg->method_name = "_request_enter";
970   emsg->env = GNUNET_ENV_environment_create ();
971   GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
972                               "_abc", "abc def", 7);
973   GNUNET_ENV_environment_add (emsg->env, GNUNET_ENV_OP_ASSIGN,
974                               "_abc_def", "abc def ghi", 11);
975   emsg->data = "let me in";
976   emsg->data_size = strlen (emsg->data) + 1;
977   emsg->msg = GNUNET_PSYC_message_create (emsg->method_name, emsg->env,
978                                           emsg->data, emsg->data_size);
979
980   gst = GNUNET_SOCIAL_guest_enter_by_name (cfg, guest_ego,
981                                            "home.host.gnu", "let.me*in!",
982                                            emsg->msg, guest_slicer,
983                                            guest_recv_local_enter,
984                                            guest_recv_entry_decision, NULL);
985   gst_plc = GNUNET_SOCIAL_guest_get_place (gst);
986 }
987
988
989 static void
990 guest_recv_add_pkey_result (void *cls, int32_t success, const char *emsg)
991 {
992   GNUNET_assert (GNUNET_YES == success);
993   guest_pkey_added = GNUNET_YES;
994 }
995
996
997 static void
998 id_guest_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
999 {
1000   GNUNET_assert (NULL != ego);
1001   guest_ego = ego;
1002   GNUNET_IDENTITY_ego_get_public_key (ego, &guest_pub_key);
1003
1004   guest_slicer = GNUNET_SOCIAL_slicer_create ();
1005   GNUNET_SOCIAL_slicer_method_add (guest_slicer, "",
1006                                    guest_recv_method, guest_recv_modifier,
1007                                    guest_recv_data, guest_recv_eom, NULL);
1008   GNUNET_SOCIAL_slicer_modifier_add (guest_slicer, "_foo_bar",
1009                                      guest_recv_mod_foo_bar, &mod_foo_bar_rcls);
1010   test = TEST_HOST_ANSWER_DOOR_ADMIT;
1011
1012   GNUNET_SOCIAL_zone_add_pkey (cfg, guest_ego, "host", &host_pub_key,
1013                                GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES),
1014                                guest_recv_add_pkey_result, NULL);
1015
1016   guest_enter ();
1017 }
1018
1019
1020 static void
1021 id_guest_created (void *cls, const char *emsg)
1022 {
1023   if (NULL != emsg)
1024   {
1025     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1026                 "Could not create guest identity: %s\n", emsg);
1027 #if ! DEBUG_TEST_SOCIAL
1028     GNUNET_assert (0);
1029 #endif
1030   }
1031
1032  GNUNET_IDENTITY_ego_lookup (cfg, guest_name, &id_guest_ego_cb, NULL);
1033 }
1034
1035
1036 static void
1037 host_entered (void *cls, int result, uint64_t max_message_id)
1038 {
1039   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Host entered to place.\n");
1040
1041   GNUNET_IDENTITY_create (id, guest_name, &id_guest_created, NULL);
1042 }
1043
1044
1045 static void
1046 id_host_ego_cb (void *cls, const struct GNUNET_IDENTITY_Ego *ego)
1047 {
1048   GNUNET_assert (NULL != ego);
1049   host_ego = ego;
1050   GNUNET_IDENTITY_ego_get_public_key (ego, &host_pub_key);
1051
1052   host_slicer = GNUNET_SOCIAL_slicer_create ();
1053   GNUNET_SOCIAL_slicer_method_add (host_slicer, "",
1054                                    &host_recv_method, &host_recv_modifier,
1055                                    &host_recv_data, &host_recv_eom, NULL);
1056
1057   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Entering to place as host.\n");
1058   hst = GNUNET_SOCIAL_host_enter (cfg, host_ego, place_key,
1059                                   GNUNET_PSYC_CHANNEL_PRIVATE, host_slicer,
1060                                   host_entered, host_answer_door,
1061                                   host_farewell, NULL);
1062   hst_plc = GNUNET_SOCIAL_host_get_place (hst);
1063 }
1064
1065
1066 static void
1067 id_host_created (void *cls, const char *emsg)
1068 {
1069   if (NULL != emsg)
1070   {
1071     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1072                 "Could not create host identity: %s\n", emsg);
1073 #if ! DEBUG_TEST_SOCIAL
1074     GNUNET_assert (0);
1075 #endif
1076   }
1077
1078   GNUNET_IDENTITY_ego_lookup (cfg, host_name, &id_host_ego_cb, NULL);
1079 }
1080
1081
1082 static void
1083 identity_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego,
1084                  void **ctx, const char *name)
1085 {
1086
1087 }
1088
1089
1090 static void
1091 core_connected (void *cls, const struct GNUNET_PeerIdentity *my_identity)
1092 {
1093   this_peer = *my_identity;
1094
1095   id = GNUNET_IDENTITY_connect (cfg, &identity_ego_cb, NULL);
1096   GNUNET_IDENTITY_create (id, host_name, &id_host_created, NULL);
1097 }
1098
1099
1100 /**
1101  * Main function of the test, run from scheduler.
1102  *
1103  * @param cls NULL
1104  * @param cfg configuration we use (also to connect to Social service)
1105  * @param peer handle to access more of the peer (not used)
1106  */
1107 static void
1108 #if DEBUG_TEST_SOCIAL
1109 run (void *cls, char *const *args, const char *cfgfile,
1110      const struct GNUNET_CONFIGURATION_Handle *c)
1111 #else
1112 run (void *cls,
1113      const struct GNUNET_CONFIGURATION_Handle *c,
1114      struct GNUNET_TESTING_Peer *peer)
1115 #endif
1116 {
1117   cfg = c;
1118   end_badly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
1119
1120   place_key = GNUNET_CRYPTO_eddsa_key_create ();
1121   GNUNET_CRYPTO_eddsa_key_get_public (place_key, &place_pub_key);
1122
1123   core = GNUNET_CORE_connect (cfg, NULL, &core_connected, NULL, NULL,
1124                               NULL, GNUNET_NO, NULL, GNUNET_NO, NULL);
1125 }
1126
1127
1128 int
1129 main (int argc, char *argv[])
1130 {
1131   res = 1;
1132 #if DEBUG_TEST_SOCIAL
1133   const struct GNUNET_GETOPT_CommandLineOption opts[] = {
1134     GNUNET_GETOPT_OPTION_END
1135   };
1136   if (GNUNET_OK != GNUNET_PROGRAM_run (argc, argv, "test-social",
1137                                        "test-social [options]",
1138                                        opts, &run, NULL))
1139     return 1;
1140 #else
1141   if (0 != GNUNET_TESTING_peer_run ("test-social", "test_social.conf", &run, NULL))
1142     return 1;
1143 #endif
1144   return res;
1145 }
1146
1147 /* end of test_social.c */