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