adding a GNUNET_memcmp_priv for constant-time comparing of data; fixes #6152 (modulo...
[oweals/gnunet.git] / src / set / test_set_intersection_result_full.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012-2014 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      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @file set/test_set_intersection_result_full.c
23  * @brief testcase for full result mode of the intersection set operation
24  * @author Christian Fuchs
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_testing_lib.h"
30 #include "gnunet_set_service.h"
31
32
33 static int ret;
34
35 static struct GNUNET_PeerIdentity local_id;
36
37 static struct GNUNET_HashCode app_id;
38
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 static struct GNUNET_SCHEDULER_Task *tt;
50
51 static struct GNUNET_SET_OperationHandle *oh1;
52
53 static struct GNUNET_SET_OperationHandle *oh2;
54
55
56 static void
57 result_cb_set1 (void *cls,
58                 const struct GNUNET_SET_Element *element,
59                 uint64_t current_size,
60                 enum GNUNET_SET_Status status)
61 {
62   static int count;
63
64   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
65               "Processing result set 1 (%d)\n",
66               status);
67   switch (status)
68   {
69   case GNUNET_SET_STATUS_OK:
70     count++;
71     break;
72
73   case GNUNET_SET_STATUS_FAILURE:
74     oh1 = NULL;
75     ret = 1;
76     break;
77
78   case GNUNET_SET_STATUS_DONE:
79     oh1 = NULL;
80     GNUNET_assert (1 == count);
81     GNUNET_SET_destroy (set1);
82     set1 = NULL;
83     if (NULL == set2)
84       GNUNET_SCHEDULER_shutdown ();
85     break;
86
87   default:
88     GNUNET_assert (0);
89   }
90 }
91
92
93 static void
94 result_cb_set2 (void *cls,
95                 const struct GNUNET_SET_Element *element,
96                 uint64_t current_size,
97                 enum GNUNET_SET_Status status)
98 {
99   static int count;
100
101   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
102               "Processing result set 2 (%d)\n",
103               status);
104   switch (status)
105   {
106   case GNUNET_SET_STATUS_OK:
107     count++;
108     break;
109
110   case GNUNET_SET_STATUS_FAILURE:
111     oh2 = NULL;
112     ret = 1;
113     break;
114
115   case GNUNET_SET_STATUS_DONE:
116     oh2 = NULL;
117     GNUNET_assert (1 == count);
118     GNUNET_SET_destroy (set2);
119     set2 = NULL;
120     if (NULL == set1)
121       GNUNET_SCHEDULER_shutdown ();
122     break;
123
124   default:
125     GNUNET_assert (0);
126   }
127 }
128
129
130 static void
131 listen_cb (void *cls,
132            const struct GNUNET_PeerIdentity *other_peer,
133            const struct GNUNET_MessageHeader *context_msg,
134            struct GNUNET_SET_Request *request)
135 {
136   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
137               "starting intersection by accepting and committing\n");
138   GNUNET_assert (NULL != context_msg);
139   GNUNET_assert (ntohs (context_msg->type) == GNUNET_MESSAGE_TYPE_DUMMY);
140   oh2 = GNUNET_SET_accept (request,
141                            GNUNET_SET_RESULT_FULL,
142                            (struct GNUNET_SET_Option[]) { 0 },
143                            &result_cb_set2,
144                            NULL);
145   GNUNET_SET_commit (oh2,
146                      set2);
147 }
148
149
150 /**
151  * Start the set operation.
152  *
153  * @param cls closure, unused
154  */
155 static void
156 start (void *cls)
157 {
158   struct GNUNET_MessageHeader context_msg;
159
160   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
161               "starting listener\n");
162   context_msg.size = htons (sizeof context_msg);
163   context_msg.type = htons (GNUNET_MESSAGE_TYPE_DUMMY);
164   listen_handle = GNUNET_SET_listen (config,
165                                      GNUNET_SET_OPERATION_INTERSECTION,
166                                      &app_id,
167                                      &listen_cb,
168                                      NULL);
169   oh1 = GNUNET_SET_prepare (&local_id,
170                             &app_id,
171                             &context_msg,
172                             GNUNET_SET_RESULT_FULL,
173                             (struct GNUNET_SET_Option[]) { 0 },
174                             &result_cb_set1,
175                             NULL);
176   GNUNET_SET_commit (oh1,
177                      set1);
178 }
179
180
181 /**
182  * Initialize the second set, continue
183  *
184  * @param cls closure, unused
185  */
186 static void
187 init_set2 (void *cls)
188 {
189   struct GNUNET_SET_Element element;
190
191   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
192               "initializing set 2\n");
193   element.element_type = 0;
194   element.data = "hello";
195   element.size = strlen (element.data);
196   GNUNET_SET_add_element (set2,
197                           &element,
198                           NULL,
199                           NULL);
200   element.data = "quux";
201   element.size = strlen (element.data);
202   GNUNET_SET_add_element (set2,
203                           &element,
204                           NULL,
205                           NULL);
206   element.data = "baz";
207   element.size = strlen (element.data);
208   GNUNET_SET_add_element (set2,
209                           &element,
210                           &start,
211                           NULL);
212 }
213
214
215 /**
216  * Initialize the first set, continue.
217  */
218 static void
219 init_set1 (void)
220 {
221   struct GNUNET_SET_Element element;
222
223   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
224               "initializing set 1\n");
225   element.element_type = 0;
226   element.data = "hello";
227   element.size = strlen (element.data);
228   GNUNET_SET_add_element (set1,
229                           &element,
230                           NULL,
231                           NULL);
232   element.data = "bar";
233   element.size = strlen (element.data);
234   GNUNET_SET_add_element (set1,
235                           &element,
236                           &init_set2,
237                           NULL);
238 }
239
240
241 static int
242 iter_cb (void *cls,
243          const struct GNUNET_SET_Element *element)
244 {
245   if (NULL == element)
246   {
247     GNUNET_assert (iter_count == 3);
248     GNUNET_SET_destroy (cls);
249     return GNUNET_YES;
250   }
251   iter_count++;
252   return GNUNET_YES;
253 }
254
255
256 static void
257 test_iter ()
258 {
259   struct GNUNET_SET_Element element;
260   struct GNUNET_SET_Handle *iter_set;
261
262   iter_set = GNUNET_SET_create (config,
263                                 GNUNET_SET_OPERATION_INTERSECTION);
264   element.element_type = 0;
265   element.data = "hello";
266   element.size = strlen (element.data);
267   GNUNET_SET_add_element (iter_set,
268                           &element,
269                           NULL,
270                           NULL);
271   element.data = "bar";
272   element.size = strlen (element.data);
273   GNUNET_SET_add_element (iter_set,
274                           &element,
275                           NULL,
276                           NULL);
277   element.data = "quux";
278   element.size = strlen (element.data);
279   GNUNET_SET_add_element (iter_set,
280                           &element,
281                           NULL,
282                           NULL);
283   GNUNET_SET_iterate (iter_set,
284                       &iter_cb,
285                       iter_set);
286 }
287
288
289 /**
290  * Function run on shutdown.
291  *
292  * @param cls closure
293  */
294 static void
295 do_shutdown (void *cls)
296 {
297   if (NULL != tt)
298   {
299     GNUNET_SCHEDULER_cancel (tt);
300     tt = NULL;
301   }
302   if (NULL != oh1)
303   {
304     GNUNET_SET_operation_cancel (oh1);
305     oh1 = NULL;
306   }
307   if (NULL != oh2)
308   {
309     GNUNET_SET_operation_cancel (oh2);
310     oh2 = NULL;
311   }
312   if (NULL != set1)
313   {
314     GNUNET_SET_destroy (set1);
315     set1 = NULL;
316   }
317   if (NULL != set2)
318   {
319     GNUNET_SET_destroy (set2);
320     set2 = NULL;
321   }
322   if (NULL != listen_handle)
323   {
324     GNUNET_SET_listen_cancel (listen_handle);
325     listen_handle = NULL;
326   }
327 }
328
329
330 /**
331  * Function run on timeout.
332  *
333  * @param cls closure
334  */
335 static void
336 timeout_fail (void *cls)
337 {
338   tt = NULL;
339   GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
340               "Testcase failed with timeout\n");
341   GNUNET_SCHEDULER_shutdown ();
342   ret = 1;
343 }
344
345
346 /**
347  * Signature of the 'main' function for a (single-peer) testcase that
348  * is run using 'GNUNET_TESTING_peer_run'.
349  *
350  * @param cls closure
351  * @param cfg configuration of the peer that was started
352  * @param peer identity of the peer that was created
353  */
354 static void
355 run (void *cls,
356      const struct GNUNET_CONFIGURATION_Handle *cfg,
357      struct GNUNET_TESTING_Peer *peer)
358 {
359   config = cfg;
360   GNUNET_TESTING_peer_get_identity (peer,
361                                     &local_id);
362   if (0)
363     test_iter ();
364
365   tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (
366                                        GNUNET_TIME_UNIT_SECONDS, 5),
367                                      &timeout_fail,
368                                      NULL);
369   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
370                                  NULL);
371
372   set1 = GNUNET_SET_create (cfg,
373                             GNUNET_SET_OPERATION_INTERSECTION);
374   set2 = GNUNET_SET_create (cfg,
375                             GNUNET_SET_OPERATION_INTERSECTION);
376   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
377                                     &app_id);
378
379   /* test the real set reconciliation */
380   init_set1 ();
381 }
382
383
384 int
385 main (int argc,
386       char **argv)
387 {
388   if (0 != GNUNET_TESTING_peer_run ("test_set_intersection_result_full",
389                                     "test_set.conf",
390                                     &run, NULL))
391     return 1;
392   return ret;
393 }