-fix off-by-1
[oweals/gnunet.git] / src / set / test_set_union_result_symmetric.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012 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 set/test_set_union_result_smmetric
23  * @brief testcase for symmetric result mode of the union set operation
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 static struct GNUNET_SET_Handle *set1;
40
41 static struct GNUNET_SET_Handle *set2;
42
43 static struct GNUNET_SET_ListenHandle *listen_handle;
44
45 static const struct GNUNET_CONFIGURATION_Handle *config;
46
47 static int iter_count;
48
49 /**
50  * Are we testing correctness for the empty set union?
51  */
52 static int empty;
53
54 /**
55  * Number of elements found in set 1
56  */
57 static unsigned int count_set1;
58
59 /**
60  * Number of elements found in set 2
61  */
62 static unsigned int count_set2;
63
64 /**
65  * Task that is run when the test times out.
66  */
67 static struct GNUNET_SCHEDULER_Task *timeout_task;
68
69
70 static void
71 result_cb_set1 (void *cls,
72                 const struct GNUNET_SET_Element *element,
73                 enum GNUNET_SET_Status status)
74 {
75   switch (status)
76   {
77     case GNUNET_SET_STATUS_ADD_LOCAL:
78       count_set1++;
79       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
80                   "set 1: got element\n");
81       break;
82     case GNUNET_SET_STATUS_FAILURE:
83       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
84                   "set 1: failure\n");
85       ret = 1;
86       if (NULL != timeout_task)
87       {
88         GNUNET_SCHEDULER_cancel (timeout_task);
89         timeout_task = NULL;
90       }
91       GNUNET_SCHEDULER_shutdown ();
92       break;
93     case GNUNET_SET_STATUS_DONE:
94       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
95                   "set 1: done\n");
96       GNUNET_SET_destroy (set1);
97       set1 = NULL;
98       if (NULL == set2)
99       {
100         if (NULL != timeout_task)
101         {
102           GNUNET_SCHEDULER_cancel (timeout_task);
103           timeout_task = NULL;
104         }
105         GNUNET_SCHEDULER_shutdown ();
106       }
107       break;
108     case GNUNET_SET_STATUS_ADD_REMOTE:
109       break;
110     default:
111       GNUNET_assert (0);
112   }
113 }
114
115
116 static void
117 result_cb_set2 (void *cls,
118                 const struct GNUNET_SET_Element *element,
119                 enum GNUNET_SET_Status status)
120 {
121   switch (status)
122   {
123     case GNUNET_SET_STATUS_ADD_LOCAL:
124       count_set2++;
125       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
126                   "set 2: got element\n");
127       break;
128     case GNUNET_SET_STATUS_FAILURE:
129       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130                   "set 2: failure\n");
131       ret = 1;
132       if (NULL != timeout_task)
133       {
134         GNUNET_SCHEDULER_cancel (timeout_task);
135         timeout_task = NULL;
136       }
137       GNUNET_SCHEDULER_shutdown ();
138       break;
139     case GNUNET_SET_STATUS_DONE:
140       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141                   "set 2: done\n");
142       GNUNET_SET_destroy (set2);
143       set2 = NULL;
144       if (NULL == set1)
145       {
146         if (NULL != timeout_task)
147         {
148           GNUNET_SCHEDULER_cancel (timeout_task);
149           timeout_task = NULL;
150         }
151         GNUNET_SCHEDULER_shutdown ();
152       }
153       break;
154     case GNUNET_SET_STATUS_ADD_REMOTE:
155       break;
156     default:
157       GNUNET_assert (0);
158   }
159 }
160
161
162 static void
163 listen_cb (void *cls,
164            const struct GNUNET_PeerIdentity *other_peer,
165            const struct GNUNET_MessageHeader *context_msg,
166            struct GNUNET_SET_Request *request)
167 {
168   struct GNUNET_SET_OperationHandle *oh;
169
170   GNUNET_assert (NULL != context_msg);
171   GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_TEST);
172   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
173               "listen cb called\n");
174   GNUNET_SET_listen_cancel (listen_handle);
175   oh = GNUNET_SET_accept (request,
176                           GNUNET_SET_RESULT_SYMMETRIC,
177                           &result_cb_set2,
178                           NULL);
179   GNUNET_SET_commit (oh, set2);
180 }
181
182
183 /**
184  * Start the set operation.
185  *
186  * @param cls closure, unused
187  */
188 static void
189 start (void *cls)
190 {
191   struct GNUNET_SET_OperationHandle *oh;
192   struct GNUNET_MessageHeader context_msg;
193
194   context_msg.size = htons (sizeof context_msg);
195   context_msg.type = htons (GNUNET_MESSAGE_TYPE_TEST);
196
197   listen_handle = GNUNET_SET_listen (config,
198                                      GNUNET_SET_OPERATION_UNION,
199                                      &app_id,
200                                      &listen_cb, NULL);
201   oh = GNUNET_SET_prepare (&local_id,
202                            &app_id,
203                            &context_msg,
204                            GNUNET_SET_RESULT_SYMMETRIC,
205                            &result_cb_set1, NULL);
206   GNUNET_SET_commit (oh, set1);
207 }
208
209
210 /**
211  * Initialize the second set, continue
212  *
213  * @param cls closure, unused
214  */
215 static void
216 init_set2 (void *cls)
217 {
218   struct GNUNET_SET_Element element;
219
220   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
221               "initializing set 2\n");
222   if (empty)
223   {
224     start (NULL);
225     return;
226   }
227   element.element_type = 0;
228   element.data = "hello";
229   element.size = strlen(element.data);
230   GNUNET_SET_add_element (set2,
231                           &element,
232                           NULL,
233                           NULL);
234   element.data = "quux";
235   element.size = strlen(element.data);
236   GNUNET_SET_add_element (set2,
237                           &element,
238                           NULL,
239                           NULL);
240   element.data = "baz";
241   element.size = strlen(element.data);
242   GNUNET_SET_add_element (set2,
243                           &element,
244                           &start, NULL);
245 }
246
247
248 /**
249  * Initialize the first set, continue.
250  */
251 static void
252 init_set1 (void)
253 {
254   struct GNUNET_SET_Element element;
255
256   if (empty)
257   {
258     init_set2 (NULL);
259     return;
260   }
261   element.element_type = 0;
262   element.data = "hello";
263   element.size = strlen(element.data);
264   GNUNET_SET_add_element (set1,
265                           &element,
266                           NULL,
267                           NULL);
268   element.data = "bar";
269   element.size = strlen(element.data);
270   GNUNET_SET_add_element (set1,
271                           &element,
272                           &init_set2,
273                           NULL);
274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
275               "initialized set 1\n");
276 }
277
278
279 static int
280 iter_cb (void *cls,
281          const struct GNUNET_SET_Element *element)
282 {
283   if (NULL == element)
284   {
285     GNUNET_assert (iter_count == 3);
286     GNUNET_SET_destroy (cls);
287     return GNUNET_YES;
288   }
289   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
290               "iter: got element\n");
291   iter_count++;
292   return GNUNET_YES;
293 }
294
295
296 static void
297 test_iter ()
298 {
299   struct GNUNET_SET_Element element;
300   struct GNUNET_SET_Handle *iter_set;
301
302   iter_count = 0;
303   iter_set = GNUNET_SET_create (config, GNUNET_SET_OPERATION_UNION);
304   element.element_type = 0;
305   element.data = "hello";
306   element.size = strlen(element.data);
307   GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
308   element.data = "bar";
309   element.size = strlen(element.data);
310   GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
311   element.data = "quux";
312   element.size = strlen(element.data);
313   GNUNET_SET_add_element (iter_set, &element, NULL, NULL);
314
315   GNUNET_SET_iterate (iter_set,
316                       &iter_cb,
317                       iter_set);
318 }
319
320
321 /**
322  * Signature of the main function of a task.
323  *
324  * @param cls closure
325  */
326 static void
327 timeout_fail (void *cls)
328 {
329   timeout_task = NULL;
330   GNUNET_SCHEDULER_shutdown ();
331   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
332               "test timed out\n");
333   ret = 1;
334 }
335
336
337 /**
338  * Signature of the 'main' function for a (single-peer) testcase that
339  * is run using 'GNUNET_TESTING_peer_run'.
340  *
341  * @param cls closure
342  * @param cfg configuration of the peer that was started
343  * @param peer identity of the peer that was created
344  */
345 static void
346 run (void *cls,
347      const struct GNUNET_CONFIGURATION_Handle *cfg,
348      struct GNUNET_TESTING_Peer *peer)
349 {
350   timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
351                                                &timeout_fail,
352                                                NULL);
353
354   config = cfg;
355   GNUNET_TESTING_peer_get_identity (peer,
356                                     &local_id);
357
358   test_iter ();
359
360   set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
361   set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION);
362   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id);
363
364   /* test the real set reconciliation */
365   init_set1 ();
366 }
367
368
369 int
370 main (int argc, char **argv)
371 {
372   empty = 1;
373   if (0 != GNUNET_TESTING_peer_run ("test_set_api",
374                                     "test_set.conf",
375                                     &run, NULL))
376   {
377     return 1;
378   }
379   GNUNET_assert (0 == count_set1);
380   GNUNET_assert (0 == count_set2);
381   empty = 0;
382   if (0 != GNUNET_TESTING_peer_run ("test_set_api",
383                                     "test_set.conf",
384                                     &run, NULL))
385   {
386     return 1;
387   }
388   GNUNET_assert (2 == count_set1);
389   GNUNET_assert (1 == count_set2);
390   return ret;
391 }