b0c4c8211f4cd60b153c30ee6fa23dc6bc06c67c
[oweals/gnunet.git] / src / namestore / test_namestore_api_zone_iteration_nick.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013 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  * @file namestore/test_namestore_api_zone_iteration.c
22  * @brief testcase for zone iteration functionality: iterate all zones
23  */
24 #include "platform.h"
25 #include "gnunet_namestore_service.h"
26 #include "gnunet_testing_lib.h"
27 #include "namestore.h"
28 #include "gnunet_dnsparser_lib.h"
29
30 #define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32 #define ZONE_NICK_1 "nick1"
33 #define ZONE_NICK_2 "nick2"
34
35 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
36
37
38 static struct GNUNET_NAMESTORE_Handle *nsh;
39
40 static struct GNUNET_CRYPTO_EcdsaPrivateKey privkey;
41
42 static struct GNUNET_CRYPTO_EcdsaPrivateKey privkey2;
43
44 static struct GNUNET_NAMESTORE_ZoneIterator *zi;
45
46 static int res;
47
48 static int returned_records;
49
50 static char *s_name_1;
51
52 static struct GNUNET_GNSRECORD_Data *s_rd_1;
53
54 static char *s_name_2;
55
56 static struct GNUNET_GNSRECORD_Data *s_rd_2;
57
58 static char *s_name_3;
59
60 static struct GNUNET_GNSRECORD_Data *s_rd_3;
61
62 static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
63
64
65 /**
66  * Re-establish the connection to the service.
67  *
68  * @param cls handle to use to re-connect.
69  * @param tc scheduler context
70  */
71 static void
72 end (void *cls)
73 {
74   if (NULL != zi)
75   {
76     GNUNET_NAMESTORE_zone_iteration_stop (zi);
77     zi = NULL;
78   }
79   if (nsh != NULL)
80   {
81     GNUNET_NAMESTORE_disconnect (nsh);
82     nsh = NULL;
83   }
84   GNUNET_free_non_null (s_name_1);
85   GNUNET_free_non_null (s_name_2);
86   GNUNET_free_non_null (s_name_3);
87
88   if (s_rd_1 != NULL)
89   {
90     GNUNET_free_nz ((void *) s_rd_1->data);
91     GNUNET_free (s_rd_1);
92   }
93   if (s_rd_2 != NULL)
94   {
95     GNUNET_free_nz ((void *) s_rd_2->data);
96     GNUNET_free (s_rd_2);
97   }
98   if (s_rd_3 != NULL)
99   {
100     GNUNET_free_nz ((void *) s_rd_3->data);
101     GNUNET_free (s_rd_3);
102   }
103 }
104
105
106 static int
107 check_zone_1 (const char *label, unsigned int rd_count,
108               const struct GNUNET_GNSRECORD_Data *rd)
109 {
110   for (unsigned int c = 0; c < rd_count; c++)
111   {
112     if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) &&
113         (0 != strcmp (rd[c].data, ZONE_NICK_1)))
114     {
115       GNUNET_break (0);
116       return GNUNET_YES;
117     }
118   }
119   return GNUNET_NO;
120 }
121
122
123 static int
124 check_zone_2 (const char *label,
125               unsigned int rd_count,
126               const struct GNUNET_GNSRECORD_Data *rd)
127 {
128   for (unsigned int c = 0; c < rd_count; c++)
129   {
130     if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) &&
131         (0 != strcmp (rd[c].data, ZONE_NICK_2)))
132     {
133       GNUNET_break (0);
134       return GNUNET_YES;
135     }
136   }
137   return GNUNET_NO;
138 }
139
140
141 static void
142 zone_proc_end (void *cls)
143 {
144   zi = NULL;
145   res = 0;
146   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
147               "Received last result, iteration done after receing %u results\n",
148               returned_records);
149   GNUNET_SCHEDULER_shutdown ();
150 }
151
152
153 static void
154 zone_proc (void *cls,
155            const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
156            const char *label,
157            unsigned int rd_count,
158            const struct GNUNET_GNSRECORD_Data *rd)
159 {
160   int failed = GNUNET_NO;
161
162   GNUNET_assert (NULL != zone);
163   if (0 == GNUNET_memcmp (zone, &privkey))
164   {
165     failed = check_zone_1 (label, rd_count, rd);
166     if (GNUNET_YES == failed)
167       GNUNET_break (0);
168   }
169   else if (0 == GNUNET_memcmp (zone, &privkey2))
170   {
171     failed = check_zone_2 (label, rd_count, rd);
172     if (GNUNET_YES == failed)
173       GNUNET_break (0);
174   }
175   else
176   {
177     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
178                 "Received invalid zone\n");
179     failed = GNUNET_YES;
180     GNUNET_break (0);
181   }
182
183   if (failed == GNUNET_NO)
184   {
185     returned_records++;
186     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
187                 "Telling namestore to send the next result\n");
188     GNUNET_NAMESTORE_zone_iterator_next (zi,
189                                          1);
190   }
191   else
192   {
193     GNUNET_break (0);
194     res = 1;
195     GNUNET_SCHEDULER_shutdown ();
196   }
197 }
198
199
200 static void
201 fail_cb (void *cls)
202 {
203   GNUNET_assert (0);
204 }
205
206
207 static void
208 put_cont (void *cls,
209           int32_t success,
210           const char *emsg)
211 {
212   static int c = 0;
213
214   if (success == GNUNET_OK)
215   {
216     c++;
217     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c);
218   }
219   else
220   {
221     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n",
222                 emsg);
223     GNUNET_break (0);
224     GNUNET_SCHEDULER_shutdown ();
225     return;
226   }
227
228   if (c == 3)
229   {
230     res = 1;
231     returned_records = 0;
232     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
233                 "All records created, starting iteration over all zones \n");
234     zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
235                                                 NULL,
236                                                 &fail_cb,
237                                                 NULL,
238                                                 &zone_proc,
239                                                 NULL,
240                                                 &zone_proc_end,
241                                                 NULL);
242     if (zi == NULL)
243     {
244       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n");
245       GNUNET_break (0);
246       GNUNET_SCHEDULER_shutdown ();
247       return;
248     }
249   }
250 }
251
252
253 static struct GNUNET_GNSRECORD_Data *
254 create_record (unsigned int count)
255 {
256   struct GNUNET_GNSRECORD_Data *rd;
257
258   rd = GNUNET_new_array (count,
259                          struct GNUNET_GNSRECORD_Data);
260   for (unsigned int c = 0; c < count; c++)
261   {
262     rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
263       GNUNET_TIME_UNIT_HOURS).abs_value_us;
264     rd[c].record_type = TEST_RECORD_TYPE;
265     rd[c].data_size = 50;
266     rd[c].data = GNUNET_malloc (50);
267     rd[c].flags = 0;
268     memset ((char *) rd[c].data, 'a', 50);
269   }
270   return rd;
271 }
272
273
274 static void
275 nick_2_cont (void *cls,
276              int32_t success,
277              const char *emsg)
278 {
279   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280               "Nick added : %s\n",
281               (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
282
283   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
284
285   GNUNET_asprintf (&s_name_1, "dummy1");
286   s_rd_1 = create_record (1);
287   GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_1,
288                                   1, s_rd_1,
289                                   &put_cont, NULL);
290
291   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292               "Created record 2 \n");
293   GNUNET_asprintf (&s_name_2, "dummy2");
294   s_rd_2 = create_record (1);
295   GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_2,
296                                   1, s_rd_2, &put_cont, NULL);
297
298   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
299               "Created record 3\n");
300
301   /* name in different zone */
302   GNUNET_asprintf (&s_name_3, "dummy3");
303   s_rd_3 = create_record (1);
304   GNUNET_NAMESTORE_records_store (nsh, &privkey2, s_name_3,
305                                   1, s_rd_3,
306                                   &put_cont, NULL);
307 }
308
309
310 static void
311 nick_1_cont (void *cls, int32_t success, const char *emsg)
312 {
313   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
314               "Nick 1 added : %s\n",
315               (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
316
317   nsqe = GNUNET_NAMESTORE_set_nick (nsh,
318                                     &privkey2, ZONE_NICK_2, &nick_2_cont,
319                                     &privkey2);
320   if (NULL == nsqe)
321   {
322     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
323                 _ ("Namestore cannot store no block\n"));
324   }
325 }
326
327
328 /**
329  * Callback called from the zone iterator when we iterate over
330  * the empty zone.  Check that we got no records and then
331  * start the actual tests by filling the zone.
332  */
333 static void
334 empty_zone_proc (void *cls,
335                  const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
336                  const char *label,
337                  unsigned int rd_count,
338                  const struct GNUNET_GNSRECORD_Data *rd)
339 {
340   GNUNET_assert (nsh == cls);
341
342   if (NULL != zone)
343   {
344     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
345                 _ ("Expected empty zone but received zone private key\n"));
346     GNUNET_break (0);
347     GNUNET_SCHEDULER_shutdown ();
348     return;
349   }
350   if ((NULL != label) || (NULL != rd) || (0 != rd_count))
351   {
352     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353                 _ ("Expected no zone content but received data\n"));
354     GNUNET_break (0);
355     GNUNET_SCHEDULER_shutdown ();
356     return;
357   }
358   GNUNET_assert (0);
359 }
360
361
362 static void
363 empty_zone_end (void *cls)
364 {
365   GNUNET_assert (nsh == cls);
366   zi = NULL;
367   GNUNET_CRYPTO_ecdsa_key_create (&privkey);
368   GNUNET_CRYPTO_ecdsa_key_create (&privkey2);
369   nsqe = GNUNET_NAMESTORE_set_nick (nsh,
370                                     &privkey,
371                                     ZONE_NICK_1,
372                                     &nick_1_cont,
373                                     NULL);
374   if (NULL == nsqe)
375   {
376     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
377                 _ ("Namestore cannot store no block\n"));
378   }
379 }
380
381
382 static void
383 run (void *cls,
384      const struct GNUNET_CONFIGURATION_Handle *cfg,
385      struct GNUNET_TESTING_Peer *peer)
386 {
387   nsh = GNUNET_NAMESTORE_connect (cfg);
388   GNUNET_break (NULL != nsh);
389   GNUNET_SCHEDULER_add_shutdown (&end,
390                                  NULL);
391   /* first, iterate over empty namestore */
392   zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
393                                               NULL,
394                                               &fail_cb,
395                                               NULL,
396                                               &empty_zone_proc,
397                                               nsh,
398                                               &empty_zone_end,
399                                               nsh);
400   if (NULL == zi)
401   {
402     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403                 "Failed to create zone iterator\n");
404     GNUNET_break (0);
405     GNUNET_SCHEDULER_shutdown ();
406   }
407 }
408
409
410 #include "test_common.c"
411
412
413 int
414 main (int argc, char *argv[])
415 {
416   const char *plugin_name;
417   char *cfg_name;
418
419   SETUP_CFG (plugin_name, cfg_name);
420   res = 1;
421   if (0 !=
422       GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-nick",
423                                cfg_name,
424                                &run,
425                                NULL))
426   {
427     res = 1;
428   }
429   GNUNET_DISK_purge_cfg_dir (cfg_name,
430                              "GNUNET_TEST_HOME");
431   GNUNET_free (cfg_name);
432   return res;
433 }
434
435
436 /* end of test_namestore_api_zone_iteration.c */