paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / set / test_set_union_copy.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2015, 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_copy.c
21  * @brief testcase for lazy copying of union sets
22  * @author Florian Dold
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_common.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_SET_Handle *set1;
39
40 static struct GNUNET_SET_Handle *set2;
41
42 static const struct GNUNET_CONFIGURATION_Handle *config;
43
44 static struct GNUNET_SCHEDULER_Task *tt;
45
46
47 static void
48 add_element_str (struct GNUNET_SET_Handle *set,
49                  char *str)
50 {
51   struct GNUNET_SET_Element element;
52
53   element.element_type = 0;
54   element.data = str;
55   element.size = strlen (str);
56   GNUNET_SET_add_element (set,
57                           &element,
58                           NULL,
59                           NULL);
60 }
61
62
63 static void
64 remove_element_str (struct GNUNET_SET_Handle *set,
65                     char *str)
66 {
67   struct GNUNET_SET_Element element;
68
69   element.element_type = 0;
70   element.data = str;
71   element.size = strlen (str);
72   GNUNET_SET_remove_element (set,
73                              &element,
74                              NULL,
75                              NULL);
76 }
77
78
79 /**
80  * Signature of the main function of a task.
81  *
82  * @param cls closure
83  */
84 static void
85 timeout_fail (void *cls)
86 {
87   tt = NULL;
88   GNUNET_SCHEDULER_shutdown ();
89   ret = 1;
90 }
91
92
93 struct CountIterClosure
94 {
95   unsigned int expected_count;
96   unsigned int ongoing_count;
97   GNUNET_SCHEDULER_TaskCallback cont;
98   void *cont_cls;
99   char *what;
100 };
101
102
103 static int
104 check_count_iter (void *cls,
105                   const struct GNUNET_SET_Element *element)
106 {
107   struct CountIterClosure *ci_cls = cls;
108
109   if (NULL == element)
110   {
111     if (ci_cls->expected_count != ci_cls->ongoing_count)
112     {
113       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
114                   "Expected count (what: %s) to be %u, but it's actually %u\n",
115                   ci_cls->what,
116                   ci_cls->expected_count,
117                   ci_cls->ongoing_count);
118       ret = 1;
119       GNUNET_SCHEDULER_shutdown ();
120       return GNUNET_NO;
121     }
122     ci_cls->cont (ci_cls->cont_cls);
123     GNUNET_free (ci_cls);
124     return GNUNET_NO;
125   }
126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
127               "Set `%s' has element %.*s\n",
128               ci_cls->what,
129               (int) element->size,
130               (const char *) element->data);
131
132   ci_cls->ongoing_count++;
133   return GNUNET_YES;
134 }
135
136
137 static void
138 check_count (struct GNUNET_SET_Handle *set,
139              char *what,
140              unsigned int expected_count,
141              GNUNET_SCHEDULER_TaskCallback cont,
142              void *cont_cls)
143 {
144   struct CountIterClosure *ci_cls = GNUNET_new (struct CountIterClosure);
145
146   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
147               "Checking count of %s\n",
148               what);
149
150   ci_cls->expected_count = expected_count;
151   ci_cls->ongoing_count = 0;
152   ci_cls->cont = cont;
153   ci_cls->cont_cls = cont_cls;
154   ci_cls->what = what;
155
156   GNUNET_assert (GNUNET_YES ==
157                  GNUNET_SET_iterate (set,
158                                      &check_count_iter,
159                                      ci_cls));
160 }
161
162
163 static void
164 test_done (void *cls)
165 {
166   GNUNET_SCHEDULER_shutdown ();
167 }
168
169
170 static void
171 check_new_set_count (void *cls)
172 {
173   check_count (set2,
174                "new set",
175                3,
176                &test_done,
177                NULL);
178 }
179
180
181 static void
182 copy_done (void *cls,
183            struct GNUNET_SET_Handle *new_set)
184 {
185   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
186               "copy done\n");
187   set2 = new_set;
188   remove_element_str (set2,
189                       "k5555");
190   add_element_str (set2,
191                    "n66666");
192   add_element_str (set2,
193                    "new2butremoved");
194   remove_element_str (set2,
195                       "new2butremoved");
196   remove_element_str (set2,
197                       "new3justremoved");
198   // Check that set1 didn't change.
199   check_count (set1,
200                "old set",
201                3,
202                &check_new_set_count,
203                NULL);
204 }
205
206
207 static void
208 test_copy (void *cls)
209 {
210   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
211               "about to copy\n");
212   GNUNET_SET_copy_lazy (set1,
213                         &copy_done,
214                         NULL);
215 }
216
217
218 /**
219  * Function run on shutdown.
220  *
221  * @param cls closure
222  */
223 static void
224 do_shutdown (void *cls)
225 {
226   if (NULL != tt)
227   {
228     GNUNET_SCHEDULER_cancel (tt);
229     tt = NULL;
230   }
231   if (NULL != set1)
232   {
233     GNUNET_SET_destroy (set1);
234     set1 = NULL;
235   }
236   if (NULL != set2)
237   {
238     GNUNET_SET_destroy (set2);
239     set2 = NULL;
240   }
241 }
242
243
244 /**
245  * Signature of the 'main' function for a (single-peer) testcase that
246  * is run using #GNUNET_TESTING_peer_run().
247  *
248  * @param cls closure
249  * @param cfg configuration of the peer that was started
250  * @param peer identity of the peer that was created
251  */
252 static void
253 run (void *cls,
254      const struct GNUNET_CONFIGURATION_Handle *cfg,
255      struct GNUNET_TESTING_Peer *peer)
256 {
257   tt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
258                                      &timeout_fail,
259                                      NULL);
260   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
261                                  NULL);
262   config = cfg;
263   GNUNET_TESTING_peer_get_identity (peer,
264                                     &local_id);
265
266   set1 = GNUNET_SET_create (cfg,
267                             GNUNET_SET_OPERATION_UNION);
268   add_element_str (set1,
269                    "333");
270   add_element_str (set1,
271                    "k444");
272   /* duplicate -- ignored */
273   add_element_str (set1,
274                    "k444");
275   remove_element_str (set1,
276                       "333");
277   /* non-existent -- ignored */
278   remove_element_str (set1,
279                       "999999999");
280   add_element_str (set1,
281                    "k5555");
282   /* duplicate -- ignored */
283   remove_element_str (set1,
284                       "333");
285   add_element_str (set1,
286                    "k2");
287
288   check_count (set1,
289                "initial test",
290                3,
291                &test_copy,
292                NULL);
293 }
294
295
296 int
297 main (int argc, char **argv)
298 {
299   if (0 != GNUNET_TESTING_peer_run ("test_set_union_copy",
300                                     "test_set.conf",
301                                     &run, NULL))
302   {
303     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
304                 "failed to start testing peer\n");
305     return 1;
306   }
307   return ret;
308 }