10d031cc41476101b59b9902d3a072910b364125
[oweals/gnunet.git] / src / set / test_set_union_result_symmetric.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2016 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20  * @file set/test_set_union_result_smmetric
21  * @brief testcase for symmetric result mode of the union set operation
22  * @author Florian Dold
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_testing_lib.h"
28 #include "gnunet_set_service.h"
29
30
31 /**
32  * Value to return from #main().
33  */
34 static int ret;
35
36 static struct GNUNET_PeerIdentity local_id;
37
38 static struct GNUNET_HashCode app_id;
39
40 static struct GNUNET_SET_Handle *set1;
41
42 static struct GNUNET_SET_Handle *set2;
43
44 static struct GNUNET_SET_ListenHandle *listen_handle;
45
46 static const struct GNUNET_CONFIGURATION_Handle *config;
47
48 static struct GNUNET_SET_OperationHandle *oh1;
49
50 static struct GNUNET_SET_OperationHandle *oh2;
51
52 static int iter_count;
53
54 /**
55  * Are we testing correctness for the empty set union?
56  */
57 static int empty;
58
59 /**
60  * Number of elements found in set 1
61  */
62 static unsigned int count_set1;
63
64 /**
65  * Number of elements found in set 2
66  */
67 static unsigned int count_set2;
68
69 /**
70  * Task that is run when the test times out.
71  */
72 static struct GNUNET_SCHEDULER_Task *timeout_task;
73
74
75 static void
76 result_cb_set1 (void *cls,
77                 const struct GNUNET_SET_Element *element,
78                 uint64_t current_size,
79                 enum GNUNET_SET_Status status)
80 {
81   switch (status)
82   {
83     case GNUNET_SET_STATUS_ADD_LOCAL:
84       count_set1++;
85       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
86                   "set 1: got element\n");
87       break;
88     case GNUNET_SET_STATUS_FAILURE:
89       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
90                   "set 1: failure\n");
91       oh1 = NULL;
92       ret = 1;
93       if (NULL != timeout_task)
94       {
95         GNUNET_SCHEDULER_cancel (timeout_task);
96         timeout_task = NULL;
97       }
98       GNUNET_SCHEDULER_shutdown ();
99       break;
100     case GNUNET_SET_STATUS_DONE:
101       oh1 = NULL;
102       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
103                   "set 1: done\n");
104       GNUNET_SET_destroy (set1);
105       set1 = NULL;
106       if (NULL == set2)
107       {
108         if (NULL != timeout_task)
109         {
110           GNUNET_SCHEDULER_cancel (timeout_task);
111           timeout_task = NULL;
112         }
113         GNUNET_SCHEDULER_shutdown ();
114       }
115       break;
116     case GNUNET_SET_STATUS_ADD_REMOTE:
117       break;
118     default:
119       GNUNET_assert (0);
120   }
121 }
122
123
124 static void
125 result_cb_set2 (void *cls,
126                 const struct GNUNET_SET_Element *element,
127                 uint64_t current_size,
128                 enum GNUNET_SET_Status status)
129 {
130   switch (status)
131   {
132     case GNUNET_SET_STATUS_ADD_LOCAL:
133       count_set2++;
134       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
135                   "set 2: got element\n");
136       break;
137     case GNUNET_SET_STATUS_FAILURE:
138       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
139                   "set 2: failure\n");
140       oh2 = NULL;
141       ret = 1;
142       if (NULL != timeout_task)
143       {
144         GNUNET_SCHEDULER_cancel (timeout_task);
145         timeout_task = NULL;
146       }
147       GNUNET_SCHEDULER_shutdown ();
148       break;
149     case GNUNET_SET_STATUS_DONE:
150       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
151                   "set 2: done\n");
152       oh2 = NULL;
153       GNUNET_SET_destroy (set2);
154       set2 = NULL;
155       if (NULL == set1)
156       {
157         if (NULL != timeout_task)
158         {
159           GNUNET_SCHEDULER_cancel (timeout_task);
160           timeout_task = NULL;
161         }
162         GNUNET_SCHEDULER_shutdown ();
163       }
164       break;
165     case GNUNET_SET_STATUS_ADD_REMOTE:
166       break;
167     default:
168       GNUNET_assert (0);
169   }
170 }
171
172
173 static void
174 listen_cb (void *cls,
175            const struct GNUNET_PeerIdentity *other_peer,
176            const struct GNUNET_MessageHeader *context_msg,
177            struct GNUNET_SET_Request *request)
178 {
179   GNUNET_assert (NULL != context_msg);
180   GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
181   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
182               "listen cb called\n");
183   oh2 = GNUNET_SET_accept (request,
184                            GNUNET_SET_RESULT_SYMMETRIC,
185                            (struct GNUNET_SET_Option[]) { 0 },
186                            &result_cb_set2,
187                            NULL);
188   GNUNET_SET_commit (oh2,
189                      set2);
190 }
191
192
193 /**
194  * Start the set operation.
195  *
196  * @param cls closure, unused
197  */
198 static void
199 start (void *cls)
200 {
201   struct GNUNET_MessageHeader context_msg;
202
203   context_msg.size = htons (sizeof context_msg);
204   context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
205
206   listen_handle = GNUNET_SET_listen (config,
207                                      GNUNET_SET_OPERATION_UNION,
208                                      &app_id,
209                                      &listen_cb, NULL);
210   oh1 = GNUNET_SET_prepare (&local_id,
211                             &app_id,
212                             &context_msg,
213                             GNUNET_SET_RESULT_SYMMETRIC,
214                             (struct GNUNET_SET_Option[]) { 0 },
215                             &result_cb_set1, NULL);
216   GNUNET_SET_commit (oh1, set1);
217 }
218
219
220 /**
221  * Initialize the second set, continue
222  *
223  * @param cls closure, unused
224  */
225 static void
226 init_set2 (void *cls)
227 {
228   struct GNUNET_SET_Element element;
229
230   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
231               "initializing set 2\n");
232   if (empty)
233   {
234     start (NULL);
235     return;
236   }
237   element.element_type = 0;
238   element.data = "hello";
239   element.size = strlen(element.data);
240   GNUNET_SET_add_element (set2,
241                           &element,
242                           NULL,
243                           NULL);
244   element.data = "quux";
245   element.size = strlen(element.data);
246   GNUNET_SET_add_element (set2,
247                           &element,
248                           NULL,
249                           NULL);
250   element.data = "baz";
251   element.size = strlen(element.data);
252   GNUNET_SET_add_element (set2,
253                           &element,
254                           &start, NULL);
255 }
256
257
258 /**
259  * Initialize the first set, continue.
260  */
261 static void
262 init_set1 (void)
263 {
264   struct GNUNET_SET_Element element;
265
266   if (empty)
267   {
268     init_set2 (NULL);
269     return;
270   }
271   element.element_type = 0;
272   element.data = "hello";
273   element.size = strlen(element.data);
274   GNUNET_SET_add_element (set1,
275                           &element,
276                           NULL,
277                           NULL);
278   element.data = "bar";
279   element.size = strlen(element.data);
280   GNUNET_SET_add_element (set1,
281                           &element,
282                           &init_set2,
283                           NULL);
284   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
285               "initialized set 1\n");
286 }
287
288
289 static int
290 iter_cb (void *cls,
291          const struct GNUNET_SET_Element *element)
292 {
293   if (NULL == element)
294   {
295     GNUNET_assert (iter_count == 3);
296     GNUNET_SET_destroy (cls);
297     return GNUNET_YES;
298   }
299   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
300               "iter: got element\n");
301   iter_count++;
302   return GNUNET_YES;
303 }
304
305
306 static void
307 test_iter ()
308 {
309   struct GNUNET_SET_Element element;
310   struct GNUNET_SET_Handle *iter_set;
311
312   iter_count = 0;
313   iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION);
314   element.element_type = 0;
315   element.data = "hello";
316   element.size = strlen(element.data);
317   GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
318   element.data = "bar";
319   element.size = strlen(element.data);
320   GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
321   element.data = "quux";
322   element.size = strlen(element.data);
323   GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
324
325   GNUNET_SET_iterate (iter_set,
326                       &iter_cb,
327                       iter_set);
328 }
329
330
331 /**
332  * Signature of the main function of a task.
333  *
334  * @param cls closure
335  */
336 static void
337 timeout_fail (void *cls)
338 {
339   timeout_task = NULL;
340   GNUNET_SCHEDULER_shutdown ();
341   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
342               "test timed out\n");
343   ret = 1;
344 }
345
346
347 /**
348  * Function run on shutdown.
349  *
350  * @param cls closure
351  */
352 static void
353 do_shutdown (void *cls)
354 {
355   if (NULL != timeout_task)
356   {
357     GNUNET_SCHEDULER_cancel (timeout_task);
358     timeout_task = NULL;
359   }
360   if (NULL != oh1)
361   {
362     GNUNET_SET_operation_cancel (oh1);
363     oh1 = NULL;
364   }
365   if (NULL != oh2)
366   {
367     GNUNET_SET_operation_cancel (oh2);
368     oh2 = NULL;
369   }
370   if (NULL != set1)
371   {
372     GNUNET_SET_destroy (set1);
373     set1 = NULL;
374   }
375   if (NULL != set2)
376   {
377     GNUNET_SET_destroy (set2);
378     set2 = NULL;
379   }
380   if (NULL != listen_handle)
381   {
382     GNUNET_SET_listen_cancel (listen_handle);
383     listen_handle = NULL;
384   }
385 }
386
387
388 /**
389  * Signature of the 'main' function for a (single-peer) testcase that
390  * is run using 'GNUNET_TESTING_peer_run'.
391  *
392  * @param cls closure
393  * @param cfg configuration of the peer that was started
394  * @param peer identity of the peer that was created
395  */
396 static void
397 run (void *cls,
398      const struct GNUNET_CONFIGURATION_Handle *cfg,
399      struct GNUNET_TESTING_Peer *peer)
400 {
401   timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
402                                                &timeout_fail,
403                                                NULL);
404   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
405                                  NULL);
406   config = cfg;
407   GNUNET_TESTING_peer_get_identity (peer,
408                                     &local_id);
409
410   if (0)
411     test_iter ();
412
413   set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
414   set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
415   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
416
417   /* test the real set reconciliation */
418   init_set1 ();
419 }
420
421
422 int
423 main (int argc, char **argv)
424 {
425   empty = 1;
426   if (0 != GNUNET_TESTING_peer_run ("test_set_api",
427                                     "test_set.conf",
428                                     &run, NULL))
429   {
430     return 1;
431   }
432   GNUNET_assert (0 == count_set1);
433   GNUNET_assert (0 == count_set2);
434   empty = 0;
435   if (0 != GNUNET_TESTING_peer_run ("test_set_api",
436                                     "test_set.conf",
437                                     &run, NULL))
438   {
439     return 1;
440   }
441   GNUNET_break (2 == count_set1);
442   GNUNET_break (1 == count_set2);
443   return ret;
444 }