-renaming testing-new.h to testing.h, bumping library versions
[oweals/gnunet.git] / src / ats / test_ats_api_scheduling_block_and_reset.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010,2011 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 ats/test_ats_api_scheduling_reset_backoff.c
22  * @brief test case for blocking suggests and blocking reset API
23  *        measure duration of initial suggest, measure blocking duration,
24  *        reset block, measure suggest, compare time
25  * @author Christian Grothoff
26  * @author Matthias Wachs
27  */
28 #include "platform.h"
29 #include "gnunet_ats_service.h"
30 #include "gnunet_testing_lib.h"
31 #include "ats.h"
32 #include "test_ats_api_common.h"
33
34 #define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 10)
35
36 static GNUNET_SCHEDULER_TaskIdentifier die_task;
37
38 static GNUNET_SCHEDULER_TaskIdentifier wait_task;
39
40 /**
41  * Scheduling handle
42  */
43 static struct GNUNET_ATS_SchedulingHandle *sched_ats;
44
45 /**
46  * Return value
47  */
48 static int ret;
49
50 /**
51  * Test address
52  */
53 static struct Test_Address test_addr;
54
55 /**
56  * Test peer
57  */
58 static struct PeerContext p;
59
60 /**
61  * HELLO address
62  */
63 struct GNUNET_HELLO_Address test_hello_address;
64
65 /**
66  * Session
67  */
68 static void *test_session;
69
70 /**
71  * Test ats info
72  */
73 struct GNUNET_ATS_Information test_ats_info[2];
74
75 /**
76  * Test ats count
77  */
78 uint32_t test_ats_count;
79
80
81 struct GNUNET_TIME_Absolute initial_start;
82
83 struct GNUNET_TIME_Relative initial_duration;
84
85 /**
86  * Blocking start
87  */
88 struct GNUNET_TIME_Absolute block_start;
89
90 struct GNUNET_TIME_Relative block_duration;
91
92 struct GNUNET_TIME_Absolute reset_block_start;
93
94 struct GNUNET_TIME_Relative reset_block_duration;
95
96 static void
97 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
98 {
99   die_task = GNUNET_SCHEDULER_NO_TASK;
100   if (wait_task != GNUNET_SCHEDULER_NO_TASK)
101   {
102     GNUNET_SCHEDULER_cancel (wait_task);
103     wait_task = GNUNET_SCHEDULER_NO_TASK;
104   }
105   if (sched_ats != NULL)
106     GNUNET_ATS_scheduling_done (sched_ats);
107   free_test_address (&test_addr);
108   ret = GNUNET_SYSERR;
109 }
110
111
112 static void
113 end ()
114 {
115   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n");
116   if (die_task != GNUNET_SCHEDULER_NO_TASK)
117   {
118     GNUNET_SCHEDULER_cancel (die_task);
119     die_task = GNUNET_SCHEDULER_NO_TASK;
120   }
121   if (wait_task != GNUNET_SCHEDULER_NO_TASK)
122   {
123     GNUNET_SCHEDULER_cancel (wait_task);
124     wait_task = GNUNET_SCHEDULER_NO_TASK;
125   }
126   GNUNET_ATS_scheduling_done (sched_ats);
127   sched_ats = NULL;
128   free_test_address (&test_addr);
129 }
130
131 static void
132 request_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
133 {
134   wait_task = GNUNET_SCHEDULER_NO_TASK;
135   GNUNET_ATS_suggest_address (sched_ats, &p.id);
136   wait_task = GNUNET_SCHEDULER_add_delayed (WAIT, &request_task, NULL);
137 }
138
139 static void
140 address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *address,
141                     struct Session *session,
142                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
143                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
144                     const struct GNUNET_ATS_Information *atsi,
145                     uint32_t ats_count)
146 {
147   static int stage = 0;
148
149   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u\n", stage);
150   if (3 == stage)
151   {
152       /* Suggestion after resetting block interval */
153       reset_block_duration = GNUNET_TIME_absolute_get_difference(reset_block_start, GNUNET_TIME_absolute_get());
154       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address suggestion after resetting blocking took about %llu ms!\n",
155                   (long long unsigned int) reset_block_duration.rel_value);
156       if ((block_duration.rel_value <= (initial_duration.rel_value * 3)) ||
157           (initial_duration.rel_value <= (block_duration.rel_value * 3)))
158       {
159         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
160                     "Address suggestion after resetting blocking (%llu ms) took about the same as initial suggestion (%llu ms)\n",
161                     (long long unsigned int) reset_block_duration.rel_value,
162                     (long long unsigned int) initial_duration.rel_value);
163         ret = 0;
164       }
165       else
166       {
167         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address suggestion after resetting blocking (%llu ms) has too big difference to initial suggestion (%llu ms)\n",
168                     (long long unsigned int) reset_block_duration.rel_value,
169                     (long long unsigned int) initial_duration.rel_value);
170         ret = 1;
171         GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
172         GNUNET_SCHEDULER_add_now (&end, NULL);
173         return;
174       }
175
176       if (((initial_duration.rel_value * 3) <= block_duration.rel_value ) &&
177           ((reset_block_duration.rel_value * 3) <= block_duration.rel_value))
178       {
179         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address suggestion after resetting blocking (%llu ms) and initial suggestion (%llu ms) much faster than with blocking (%llu ms)\n",
180                     (long long unsigned int) reset_block_duration.rel_value,
181                     (long long unsigned int) initial_duration.rel_value,
182                     (long long unsigned int) block_duration.rel_value);
183         ret = 0;
184       }
185       else
186       {
187         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Address suggestion after resetting blocking (%llu ms) and initial suggestion (%llu ms) not faster than with blocking (%llu ms)\n",
188                     (long long unsigned int) reset_block_duration.rel_value,
189                     (long long unsigned int) initial_duration.rel_value,
190                     (long long unsigned int) block_duration.rel_value);
191         ret = 1;
192       }
193
194
195       GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
196       GNUNET_SCHEDULER_add_now (&end, NULL);
197
198   }
199   if (2 == stage)
200   {
201       /* Suggestion after block*/
202       block_duration = GNUNET_TIME_absolute_get_difference(block_start, GNUNET_TIME_absolute_get());
203       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Address suggestion was blocked for about %llu ms!\n",
204                   (long long unsigned int) block_duration.rel_value);
205
206       if (GNUNET_OK == compare_addresses (address, session, &test_hello_address, test_session))
207       {
208           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n", stage,
209                       GNUNET_i2s (&address->peer));
210           ret = 0;
211       }
212       else
213       {
214           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with invalid address `%s'\n", stage,
215                       GNUNET_i2s (&address->peer));
216           GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
217           GNUNET_SCHEDULER_add_now (&end, NULL);
218           ret = 1;
219       }
220
221       if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count))
222       {
223         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n");
224         GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
225         GNUNET_SCHEDULER_add_now (&end, NULL);
226         ret = 1;
227       }
228       stage ++;
229
230       /* Reset block interval */
231       GNUNET_ATS_reset_backoff (sched_ats, &address->peer);
232       reset_block_start = GNUNET_TIME_absolute_get();
233       GNUNET_ATS_suggest_address (sched_ats, &p.id);
234   }
235   if (1 == stage)
236   {
237     /* Initial suggestion */
238     if (GNUNET_OK == compare_addresses (address, session, &test_hello_address, test_session))
239     {
240         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n", stage,
241                     GNUNET_i2s (&address->peer));
242         ret = 0;
243     }
244     else
245     {
246         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with invalid address `%s'\n", stage,
247                     GNUNET_i2s (&address->peer));
248         GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
249         GNUNET_SCHEDULER_add_now (&end, NULL);
250         ret = 1;
251     }
252
253     if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count))
254     {
255       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n");
256       GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
257       GNUNET_SCHEDULER_add_now (&end, NULL);
258       ret = 1;
259     }
260     stage ++;
261     initial_duration = GNUNET_TIME_absolute_get_difference(initial_start, GNUNET_TIME_absolute_get());
262     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %u: Initial suggestion took about %llu ms\n", stage,
263                 (long long unsigned int) block_duration.rel_value);
264
265     block_start = GNUNET_TIME_absolute_get();
266     wait_task = GNUNET_SCHEDULER_add_delayed (WAIT, &request_task, NULL);
267   }
268   if (0 == stage)
269   {
270     /* Startup suggestion */
271     if (GNUNET_OK == compare_addresses (address, session, &test_hello_address, test_session))
272     {
273         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with correct address `%s'\n", stage,
274                     GNUNET_i2s (&address->peer));
275         ret = 0;
276     }
277     else
278     {
279         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stage %u: Callback with invalid address `%s'\n", stage,
280                     GNUNET_i2s (&address->peer));
281         GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
282         GNUNET_SCHEDULER_add_now (&end, NULL);
283         ret = 1;
284     }
285
286     if (GNUNET_OK != compare_ats(atsi, ats_count, test_ats_info, test_ats_count))
287     {
288       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %u: Callback with incorrect ats info \n");
289       GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
290       GNUNET_SCHEDULER_add_now (&end, NULL);
291       ret = 1;
292     }
293     stage ++;
294
295     GNUNET_ATS_suggest_address_cancel (sched_ats, &p.id);
296
297     initial_start = GNUNET_TIME_absolute_get();
298     GNUNET_ATS_suggest_address (sched_ats, &p.id);
299   }
300 }
301
302
303 static void
304 run (void *cls, 
305      const struct GNUNET_CONFIGURATION_Handle *cfg,
306      struct GNUNET_TESTING_Peer *peer)
307 {
308
309   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
310
311   /* Connect to ATS scheduling */
312   sched_ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
313   if (sched_ats == NULL)
314   {
315     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not connect to ATS scheduling!\n");
316     ret = 1;
317     end ();
318     return;
319   }
320
321   /* Set up peer */
322   if (GNUNET_SYSERR == GNUNET_CRYPTO_hash_from_string(PEERID0, &p.id.hashPubKey))
323   {
324       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not setup peer!\n");
325       ret = GNUNET_SYSERR;
326       end ();
327       return;
328   }
329   GNUNET_assert (0 == strcmp (PEERID0, GNUNET_i2s_full (&p.id)));
330
331   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer `%s'\n",
332               GNUNET_i2s_full(&p.id));
333
334   /* Prepare ATS Information */
335   test_ats_info[0].type = htonl (GNUNET_ATS_NETWORK_TYPE);
336   test_ats_info[0].value = htonl(GNUNET_ATS_NET_WAN);
337   test_ats_info[1].type = htonl (GNUNET_ATS_QUALITY_NET_DISTANCE);
338   test_ats_info[1].value = htonl(1);
339   test_ats_count = 2;
340
341   /* Adding address without session */
342   test_session = &test_addr;
343   create_test_address (&test_addr, "test", test_session, "test", strlen ("test") + 1);
344   test_hello_address.peer = p.id;
345   test_hello_address.transport_name = test_addr.plugin;
346   test_hello_address.address = test_addr.addr;
347   test_hello_address.address_length = test_addr.addr_len;
348   GNUNET_ATS_address_add (sched_ats, &test_hello_address, test_session, test_ats_info, test_ats_count);
349
350   initial_start = GNUNET_TIME_absolute_get();
351   GNUNET_ATS_suggest_address (sched_ats, &p.id);
352 }
353
354
355 int
356 main (int argc, char *argv[])
357 {
358   if (0 != GNUNET_TESTING_peer_run ("test_ats_api_scheduling_add_address",
359                                     "test_ats_api.conf",
360                                     &run, NULL))
361     return 1;
362   return ret;
363 }
364 /* end of file test_ats_api_scheduling_reset_backoff.c */