-use simpler, modern scheduler API
[oweals/gnunet.git] / src / dht / test_dht_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2015 Christian Grothoff (and other contributing authors)
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  * @file dht/test_dht_api.c
22  * @brief base test case for dht api
23  *
24  * This test case tests DHT api to DUMMY DHT service communication.
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_hello_lib.h"
29 #include "gnunet_testing_lib.h"
30 #include "gnunet_dht_service.h"
31
32
33 /**
34  * How long until we really give up on a particular testcase portion?
35  */
36 #define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
37
38 /**
39  * How long until we give up on any particular operation (and retry)?
40  */
41 #define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
42
43 #define MTYPE 12345
44
45
46 struct RetryContext
47 {
48   /**
49    * When to really abort the operation.
50    */
51   struct GNUNET_TIME_Absolute real_timeout;
52
53   /**
54    * What timeout to set for the current attempt (increases)
55    */
56   struct GNUNET_TIME_Relative next_timeout;
57
58   /**
59    * The task identifier of the retry task, so it can be cancelled.
60    */
61   struct GNUNET_SCHEDULER_Task * retry_task;
62
63 };
64
65
66 static struct GNUNET_DHT_Handle *dht_handle;
67
68 static struct GNUNET_DHT_GetHandle *get_handle;
69
70 struct RetryContext retry_context;
71
72 static int ok = 1;
73
74 static struct GNUNET_SCHEDULER_Task * die_task;
75
76
77 #if VERBOSE
78 #define OKPP do { ok++; FPRINTF (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
79 #else
80 #define OKPP do { ok++; } while (0)
81 #endif
82
83
84 static void
85 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
86 {
87   GNUNET_SCHEDULER_cancel (die_task);
88   die_task = NULL;
89   GNUNET_DHT_disconnect (dht_handle);
90   dht_handle = NULL;
91   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
92               "DHT disconnected, returning success!\n");
93   ok = 0;
94 }
95
96
97 static void
98 end_badly ()
99 {
100   /* do work here */
101   FPRINTF (stderr, "%s",  "Ending on an unhappy note.\n");
102   if (get_handle != NULL)
103   {
104     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping get request!\n");
105     GNUNET_DHT_get_stop (get_handle);
106   }
107   if (retry_context.retry_task != NULL)
108     GNUNET_SCHEDULER_cancel (retry_context.retry_task);
109   GNUNET_DHT_disconnect (dht_handle);
110   dht_handle = NULL;
111   ok = 1;
112 }
113
114
115 /**
116  * Signature of the main function of a task.
117  *
118  * @param cls closure
119  * @param tc context information (why was this task triggered now)
120  */
121 static void
122 test_get_stop (void *cls,
123                const struct GNUNET_SCHEDULER_TaskContext *tc)
124 {
125   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
126               "Called test_get_stop!\n");
127   GNUNET_assert (NULL != dht_handle);
128   GNUNET_DHT_get_stop (get_handle);
129   get_handle = NULL;
130   GNUNET_SCHEDULER_add_now (&end, NULL);
131 }
132
133
134 static void
135 test_get_iterator (void *cls, struct GNUNET_TIME_Absolute exp,
136                    const struct GNUNET_HashCode * key,
137                    const struct GNUNET_PeerIdentity *get_path,
138                    unsigned int get_path_length,
139                    const struct GNUNET_PeerIdentity *put_path,
140                    unsigned int put_path_length,
141                    enum GNUNET_BLOCK_Type type,
142                    size_t size, const void *data)
143 {
144   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
145               "test_get_iterator called (we got a result), stopping get request!\n");
146   GNUNET_SCHEDULER_add_now (&test_get_stop,
147                             NULL);
148 }
149
150
151 /**
152  * Signature of the main function of a task.
153  *
154  * @param cls closure
155  * @param success result of PUT
156  */
157 static void
158 test_get (void *cls, int success)
159 {
160   struct GNUNET_HashCode hash;
161
162   memset (&hash,
163           42,
164           sizeof (struct GNUNET_HashCode));
165
166   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
167               "Called test_get!\n");
168   GNUNET_assert (dht_handle != NULL);
169   retry_context.real_timeout = GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT);
170   retry_context.next_timeout = BASE_TIMEOUT;
171
172   get_handle =
173       GNUNET_DHT_get_start (dht_handle,
174                             GNUNET_BLOCK_TYPE_TEST, &hash, 1,
175                             GNUNET_DHT_RO_NONE, NULL, 0, &test_get_iterator,
176                             NULL);
177
178   if (get_handle == NULL)
179   {
180     GNUNET_break (0);
181     GNUNET_SCHEDULER_cancel (die_task);
182     die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
183     return;
184   }
185 }
186
187
188 static void
189 run (void *cls,
190      const struct GNUNET_CONFIGURATION_Handle *cfg,
191      struct GNUNET_TESTING_Peer *peer)
192 {
193   struct GNUNET_HashCode hash;
194   char *data;
195   size_t data_size = 42;
196
197   GNUNET_assert (ok == 1);
198   OKPP;
199   die_task =
200       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
201                                     (GNUNET_TIME_UNIT_MINUTES, 1), &end_badly,
202                                     NULL);
203
204
205   memset (&hash, 42, sizeof (struct GNUNET_HashCode));
206   data = GNUNET_malloc (data_size);
207   memset (data, 43, data_size);
208   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Called test_put!\n");
209   dht_handle = GNUNET_DHT_connect (cfg, 100);
210   GNUNET_assert (dht_handle != NULL);
211   GNUNET_DHT_put (dht_handle, &hash, 1, GNUNET_DHT_RO_NONE,
212                   GNUNET_BLOCK_TYPE_TEST, data_size, data,
213                   GNUNET_TIME_relative_to_absolute (TOTAL_TIMEOUT),
214                   TOTAL_TIMEOUT, &test_get, NULL);
215   GNUNET_free (data);
216 }
217
218
219 int
220 main (int argc, char *argv[])
221 {
222   if (0 != GNUNET_TESTING_peer_run ("test-dht-api",
223                                     "test_dht_api_data.conf",
224                                     &run, NULL))
225     return 1;
226   return ok;
227 }
228
229 /* end of test_dht_api.c */