error handling
[oweals/gnunet.git] / src / namestore / test_namestore_api_monitoring.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2013, 2018 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_monitoring.c
22  * @brief testcase for zone monitoring functionality: monitor first, then add records
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
33 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
34
35
36 static struct GNUNET_NAMESTORE_Handle *nsh;
37
38 static struct GNUNET_SCHEDULER_Task *endbadly_task;
39
40 static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
41
42 static struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey2;
43
44 static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
45
46 static int res;
47
48 static char *s_name_1;
49
50 static struct GNUNET_GNSRECORD_Data *s_rd_1;
51
52 static char *s_name_2;
53
54 static struct GNUNET_GNSRECORD_Data *s_rd_2;
55
56 static char *s_name_3;
57
58 static struct GNUNET_GNSRECORD_Data *s_rd_3;
59
60 struct GNUNET_NAMESTORE_QueueEntry *ns_ops[3];
61
62
63 static void
64 do_shutdown ()
65 {
66   if (NULL != zm)
67   {
68     GNUNET_NAMESTORE_zone_monitor_stop (zm);
69     zm = NULL;
70   }
71   if (NULL != ns_ops[0])
72   {
73     GNUNET_NAMESTORE_cancel (ns_ops[0]);
74     ns_ops[0] = NULL;
75   }
76   if (NULL != ns_ops[1])
77   {
78     GNUNET_NAMESTORE_cancel (ns_ops[1]);
79     ns_ops[1] = NULL;
80   }
81   if (NULL != ns_ops[2])
82   {
83     GNUNET_NAMESTORE_cancel (ns_ops[2]);
84     ns_ops[2] = NULL;
85   }
86   if (NULL != nsh)
87   {
88     GNUNET_NAMESTORE_disconnect (nsh);
89     nsh = NULL;
90   }
91   GNUNET_free_non_null (s_name_1);
92   GNUNET_free_non_null (s_name_2);
93   GNUNET_free_non_null (s_name_3);
94
95   if (s_rd_1 != NULL)
96   {
97     GNUNET_free ((void *) s_rd_1->data);
98     GNUNET_free (s_rd_1);
99   }
100   if (s_rd_2 != NULL)
101   {
102     GNUNET_free ((void *) s_rd_2->data);
103     GNUNET_free (s_rd_2);
104   }
105   if (s_rd_3 != NULL)
106   {
107     GNUNET_free ((void *) s_rd_3->data);
108     GNUNET_free (s_rd_3);
109   }
110
111   if (NULL != privkey)
112   {
113     GNUNET_free (privkey);
114     privkey = NULL;
115   }
116   if (NULL != privkey2)
117   {
118     GNUNET_free (privkey2);
119     privkey2 = NULL;
120   }
121 }
122
123
124 /**
125  * Re-establish the connection to the service.
126  *
127  * @param cls handle to use to re-connect.
128  */
129 static void
130 endbadly (void *cls)
131 {
132   do_shutdown ();
133   res = 1;
134 }
135
136
137 static void
138 end (void *cls)
139 {
140   do_shutdown ();
141   res = 0;
142 }
143
144
145 static void
146 zone_proc (void *cls,
147            const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
148            const char *name,
149            unsigned int rd_count,
150            const struct GNUNET_GNSRECORD_Data *rd)
151 {
152   static int returned_records;
153   static int fail = GNUNET_NO;
154
155   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
156               "Comparing results name %s\n",
157               name);
158   if (0 != GNUNET_memcmp (zone_key,
159                           privkey))
160   {
161     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162                 "Monitoring returned wrong zone key\n");
163     GNUNET_break (0);
164     GNUNET_SCHEDULER_cancel (endbadly_task);
165     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
166     return;
167   }
168
169   if (0 == strcmp (name, s_name_1))
170   {
171     if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
172     {
173       GNUNET_break (0);
174       fail = GNUNET_YES;
175     }
176   }
177   else if (0 == strcmp (name, s_name_2))
178   {
179     if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2))
180     {
181       GNUNET_break (0);
182       fail = GNUNET_YES;
183     }
184   }
185   else
186   {
187     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188                 "Invalid name %s\n",
189                 name);
190     GNUNET_break (0);
191     fail = GNUNET_YES;
192   }
193   GNUNET_NAMESTORE_zone_monitor_next (zm,
194                                       1);
195   if (2 == ++returned_records)
196   {
197     if (endbadly_task != NULL)
198     {
199       GNUNET_SCHEDULER_cancel (endbadly_task);
200       endbadly_task = NULL;
201     }
202     if (GNUNET_YES == fail)
203       GNUNET_SCHEDULER_add_now (&endbadly, NULL);
204     else
205       GNUNET_SCHEDULER_add_now (&end, NULL);
206   }
207 }
208
209
210 static void
211 put_cont (void *cls,
212           int32_t success,
213           const char *emsg)
214 {
215   static int c = 0;
216   char *label = cls;
217
218   if (0 == strcmp (label, s_name_1))
219     ns_ops[0] = NULL;
220   else if (0 == strcmp (label, s_name_2))
221     ns_ops[1] = NULL;
222   else if (0 == strcmp (label, s_name_3))
223     ns_ops[2] = NULL;
224
225   if (success == GNUNET_OK)
226   {
227     c++;
228     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
229                 "Created record %u: `%s'\n",
230                 c,
231                 label);
232   }
233   else
234   {
235     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
236                 "Failed to create record `%s'\n",
237                 label);
238     GNUNET_break (0);
239     GNUNET_SCHEDULER_cancel (endbadly_task);
240     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly,
241                                               NULL);
242   }
243 }
244
245
246 static struct GNUNET_GNSRECORD_Data *
247 create_record (unsigned int count)
248 {
249   struct GNUNET_GNSRECORD_Data *rd;
250
251   rd = GNUNET_new_array (count,
252                          struct GNUNET_GNSRECORD_Data);
253   for (unsigned int c = 0; c < count; c++)
254   {
255     rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
256       GNUNET_TIME_UNIT_HOURS).abs_value_us;
257     rd[c].record_type = TEST_RECORD_TYPE;
258     rd[c].data_size = 50;
259     rd[c].data = GNUNET_malloc (50);
260     rd[c].flags = 0;
261     memset ((char *) rd[c].data, 'a', 50);
262   }
263   return rd;
264 }
265
266
267 static void
268 fail_cb (void *cls)
269 {
270   GNUNET_assert (0);
271 }
272
273
274 static void
275 sync_cb (void *cls)
276 {
277   /* do nothing */
278 }
279
280
281 static void
282 run (void *cls,
283      const struct GNUNET_CONFIGURATION_Handle *cfg,
284      struct GNUNET_TESTING_Peer *peer)
285 {
286   res = 1;
287   privkey = GNUNET_CRYPTO_ecdsa_key_create ();
288   GNUNET_assert (privkey != NULL);
289
290   /* Start monitoring */
291   zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
292                                             privkey,
293                                             GNUNET_YES,
294                                             &fail_cb,
295                                             NULL,
296                                             &zone_proc,
297                                             NULL,
298                                             &sync_cb,
299                                             NULL);
300   if (NULL == zm)
301   {
302     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
303                 "Failed to create zone monitor\n");
304     GNUNET_break (0);
305     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
306     return;
307   }
308
309   endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL);
310   /* Connect to namestore */
311   nsh = GNUNET_NAMESTORE_connect (cfg);
312   if (NULL == nsh)
313   {
314     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connect to namestore\n");
315     GNUNET_break (0);
316     endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
317     return;
318   }
319
320   privkey2 = GNUNET_CRYPTO_ecdsa_key_create ();
321   GNUNET_assert (privkey2 != NULL);
322
323
324   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
325               "Created record 3\n");
326   /* name in different zone */
327   GNUNET_asprintf (&s_name_3, "dummy3");
328   s_rd_3 = create_record (1);
329   GNUNET_assert (NULL != (ns_ops[2] =
330                             GNUNET_NAMESTORE_records_store (nsh,
331                                                             privkey2,
332                                                             s_name_3,
333                                                             1,
334                                                             s_rd_3,
335                                                             &put_cont,
336                                                             s_name_3)));
337   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338               "Created record 1\n");
339   GNUNET_asprintf (&s_name_1, "dummy1");
340   s_rd_1 = create_record (1);
341   GNUNET_assert (NULL != (ns_ops[0] =
342                             GNUNET_NAMESTORE_records_store (nsh,
343                                                             privkey,
344                                                             s_name_1,
345                                                             1,
346                                                             s_rd_1,
347                                                             &put_cont,
348                                                             s_name_1)));
349
350
351   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n");
352   GNUNET_asprintf (&s_name_2, "dummy2");
353   s_rd_2 = create_record (1);
354   GNUNET_assert (NULL != (ns_ops[1] =
355                             GNUNET_NAMESTORE_records_store (nsh,
356                                                             privkey,
357                                                             s_name_2,
358                                                             1,
359                                                             s_rd_2,
360                                                             &put_cont,
361                                                             s_name_2)));
362 }
363
364
365 #include "test_common.c"
366
367
368 int
369 main (int argc,
370       char *argv[])
371 {
372   const char *plugin_name;
373   char *cfg_name;
374
375   SETUP_CFG (plugin_name, cfg_name);
376   res = 1;
377   if (0 !=
378       GNUNET_TESTING_peer_run ("test-namestore-api-monitoring",
379                                cfg_name,
380                                &run,
381                                NULL))
382   {
383     res = 1;
384   }
385   GNUNET_DISK_purge_cfg_dir (cfg_name,
386                              "GNUNET_TEST_HOME");
387   GNUNET_free (cfg_name);
388   return res;
389 }
390
391
392 /* end of test_namestore_api_monitoring.c */