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