- stage 3
[oweals/gnunet.git] / src / ats / test_ats_api_performance.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_performance.c
22  * @brief test adding addresses in automatic transport selection performance API
23  * @author Christian Grothoff
24  * @author Matthias Wachs
25  */
26 #include "platform.h"
27 #include "gnunet_ats_service.h"
28 #include "gnunet_testing_lib-new.h"
29 #include "ats.h"
30
31 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
32
33 static GNUNET_SCHEDULER_TaskIdentifier die_task;
34
35 struct GNUNET_CONFIGURATION_Handle *cfg;
36
37 static struct GNUNET_ATS_SchedulingHandle *ats;
38 static struct GNUNET_ATS_PerformanceHandle *ph;
39 struct GNUNET_ATS_AddressListHandle* phal;
40
41 static int ret;
42
43 struct Address
44 {
45   char *plugin;
46   size_t plugin_len;
47
48   void *addr;
49   size_t addr_len;
50
51   struct GNUNET_ATS_Information *ats;
52   int ats_count;
53
54   void *session;
55 };
56
57 struct PeerContext
58 {
59   struct GNUNET_PeerIdentity id;
60
61   struct Address *addr;
62 };
63
64
65
66 static struct PeerContext p[2];
67
68 static struct Address p0_addresses[2];
69 static struct Address p1_addresses[2];
70
71 struct GNUNET_HELLO_Address p0_ha[2];
72 struct GNUNET_HELLO_Address p1_ha[2];
73
74 static unsigned int stage = 0;
75
76 static void
77 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
78 {
79   die_task = GNUNET_SCHEDULER_NO_TASK;
80
81   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout in stage %u\n", stage);
82
83   if (NULL != ats)
84   GNUNET_ATS_scheduling_done (ats);
85   if (phal != NULL)
86     GNUNET_ATS_performance_list_addresses_cancel (phal);
87   phal = NULL;
88   if (ph != NULL)
89     GNUNET_ATS_performance_done (ph);
90   ph = NULL;
91
92   GNUNET_free_non_null (p0_addresses[0].addr);
93   GNUNET_free_non_null (p0_addresses[1].addr);
94   GNUNET_free_non_null (p1_addresses[0].addr);
95   GNUNET_free_non_null (p1_addresses[1].addr);
96
97   ret = GNUNET_SYSERR;
98 }
99
100
101 static void
102 end ()
103 {
104   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down\n");
105   if (die_task != GNUNET_SCHEDULER_NO_TASK)
106   {
107     GNUNET_SCHEDULER_cancel (die_task);
108     die_task = GNUNET_SCHEDULER_NO_TASK;
109   }
110   if (NULL != ats)
111   GNUNET_ATS_scheduling_done (ats);
112   if (phal != NULL)
113     GNUNET_ATS_performance_list_addresses_cancel (phal);
114   phal = NULL;
115   if (ph != NULL)
116     GNUNET_ATS_performance_done (ph);
117   ph = NULL;
118
119   GNUNET_free_non_null (p0_addresses[0].addr);
120   GNUNET_free_non_null (p0_addresses[1].addr);
121   GNUNET_free_non_null (p1_addresses[0].addr);
122   GNUNET_free_non_null (p1_addresses[1].addr);
123
124   ret = 0;
125 }
126
127 static void
128 test_performance_api (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
129
130 void all_active_addresses_peer_cb (void *cls,
131                       const struct
132                       GNUNET_HELLO_Address *
133                       address,
134                       struct
135                       GNUNET_BANDWIDTH_Value32NBO
136                       bandwidth_out,
137                       struct
138                       GNUNET_BANDWIDTH_Value32NBO
139                       bandwidth_in,
140                       const struct
141                       GNUNET_ATS_Information *
142                       ats, uint32_t ats_count)
143 {
144
145 }
146
147 void all_active_addresses_cb (void *cls,
148                       const struct
149                       GNUNET_HELLO_Address *
150                       address,
151                       struct
152                       GNUNET_BANDWIDTH_Value32NBO
153                       bandwidth_out,
154                       struct
155                       GNUNET_BANDWIDTH_Value32NBO
156                       bandwidth_in,
157                       const struct
158                       GNUNET_ATS_Information *
159                       ats, uint32_t ats_count)
160 {
161   static int cb = 0;
162   int fail = GNUNET_NO;
163
164   if (address != NULL)
165   {
166       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'  address `%s'\n",
167            GNUNET_i2s (&address->peer), address->address);
168
169     if (0 == memcmp (&address->peer, &p[0].id,
170                      sizeof (struct GNUNET_PeerIdentity)))
171     {
172         if (0 == strcmp(address->address, p0_addresses[0].addr))
173         {
174           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 0 address 0\n");
175           cb ++;
176         }
177         else
178         {
179           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected callback for peer 0 address 0!\n");
180           GNUNET_ATS_performance_list_addresses_cancel (phal);
181           fail = GNUNET_YES;
182         }
183     }
184
185     if (0 == memcmp (&address->peer, &p[1].id,
186                      sizeof (struct GNUNET_PeerIdentity)))
187     {
188         if (0 == strcmp(address->address, p1_addresses[1].addr))
189         {
190           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 1 address 1\n");
191           cb ++;
192         }
193         else
194         {
195           GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expected callback for peer 1 address 1!\n");
196           GNUNET_ATS_performance_list_addresses_cancel (phal);
197           fail = GNUNET_YES;
198         }
199     }
200     cb ++;
201   }
202   if ((address == NULL) || (GNUNET_YES == fail))
203   {
204       phal = NULL;
205       if ((2 == cb) && (GNUNET_NO == fail))
206       {
207         /* Received all addresses + terminator cb, next stage */
208         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i:  SUCCESS\n", stage);
209         GNUNET_SCHEDULER_add_now (&test_performance_api, NULL);
210         return;
211       }
212       else
213       {
214         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i:  FAIL\n", stage);
215         GNUNET_SCHEDULER_add_now (&end, NULL);
216         ret = 5;
217         return;
218       }
219   }
220 }
221
222
223
224 void all_addresses_peer_cb (void *cls,
225                       const struct
226                       GNUNET_HELLO_Address *
227                       address,
228                       struct
229                       GNUNET_BANDWIDTH_Value32NBO
230                       bandwidth_out,
231                       struct
232                       GNUNET_BANDWIDTH_Value32NBO
233                       bandwidth_in,
234                       const struct
235                       GNUNET_ATS_Information *
236                       ats, uint32_t ats_count)
237 {
238   static int cb = 0;
239   int fail = GNUNET_NO;
240
241   if (address != NULL)
242   {
243       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'  address `%s'\n",
244            GNUNET_i2s (&address->peer), address->address);
245
246     if (0 != memcmp (&address->peer, &p[1].id,
247                      sizeof (struct GNUNET_PeerIdentity)))
248     {
249         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i:  Received address for wrong peer\n", stage);
250         GNUNET_ATS_performance_list_addresses_cancel (phal);
251         fail = GNUNET_YES;
252         ret = 4;
253     }
254     cb ++;
255   }
256
257   if ((NULL == address) || (fail))
258   {
259       phal = NULL;
260       if ((2 == cb) && (GNUNET_NO == fail))
261       {
262         /* Received all addresses + terminator cb, next stage */
263         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i:  SUCCESS\n", stage);
264         GNUNET_SCHEDULER_add_now (&test_performance_api, NULL);
265         return;
266       }
267       else
268       {
269         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i:  FAIL\n", stage);
270         GNUNET_SCHEDULER_add_now (&end, NULL);
271         ret = 5;
272         return;
273       }
274   }
275 }
276
277 void all_addresses_cb (void *cls,
278                               const struct
279                               GNUNET_HELLO_Address *
280                               address,
281                               struct
282                               GNUNET_BANDWIDTH_Value32NBO
283                               bandwidth_out,
284                               struct
285                               GNUNET_BANDWIDTH_Value32NBO
286                               bandwidth_in,
287                               const struct
288                               GNUNET_ATS_Information *
289                               ats, uint32_t ats_count)
290 {
291   static int cb = 0;
292
293   if (address != NULL)
294   {
295       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer `%s'  address `%s'\n",
296            GNUNET_i2s (&address->peer), address->address);
297
298     if (0 == memcmp (&address->peer, &p[0].id,
299                      sizeof (struct GNUNET_PeerIdentity)))
300     {
301       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 0 `%s'\n", GNUNET_i2s (&address->peer));
302       if (0 == strcmp(address->address, p0_addresses[0].addr))
303       {
304         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 0 address 0\n");
305         cb |= 1;
306       }
307       if (0 == strcmp(address->address, p0_addresses[1].addr))
308       {
309         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 0 address 1\n");
310         cb |= 2;
311       }
312     }
313     if (0 == memcmp (&address->peer, &p[1].id,
314                      sizeof (struct GNUNET_PeerIdentity)));
315     {
316         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 1 `%s'\n", GNUNET_i2s (&address->peer));
317         if (0 == strcmp(address->address, p1_addresses[0].addr))
318         {
319           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 1 address 0\n");
320           cb |= 4;
321         }
322         if (0 == strcmp(address->address, p1_addresses[1].addr))
323         {
324           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for peer 1 address 1\n");
325           cb |= 8;
326         }
327     }
328   }
329   else
330   {
331       phal = NULL;
332       if (((1 << 4) - 1) == cb)
333       {
334         /* Received all addresses + terminator cb, next stage */
335         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stage %i:  SUCCESS\n", stage);
336         GNUNET_SCHEDULER_add_now (&test_performance_api, NULL);
337         return;
338       }
339       else
340       {
341         GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Stage %i:  FAIL\n", stage);
342         GNUNET_SCHEDULER_add_now (&end, NULL);
343         ret = 3;
344         return;
345       }
346   }
347 }
348
349 static void
350 test_performance_api (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
351 {
352   if (NULL == ph)
353     ph = GNUNET_ATS_performance_init (cfg, NULL, NULL);
354   if (NULL == ph)
355   {
356       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to initialize performance handle\n");
357       ret = 2;
358   }
359   stage++;
360   switch (stage) {
361     case 1: /* Get all peers, all addresses */
362       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 1: \n");
363       phal = GNUNET_ATS_performance_list_addresses (ph,
364                                              NULL,
365                                              GNUNET_YES,
366                                              &all_addresses_cb, NULL);
367       GNUNET_assert (NULL != phal);
368       break;
369     case 2: /* Get specific peer, all addresses */
370       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 2: \n");
371       phal = GNUNET_ATS_performance_list_addresses (ph,
372                                              &p[1].id,
373                                              GNUNET_YES,
374                                              &all_addresses_peer_cb, NULL);
375       GNUNET_assert (NULL != phal);
376       break;
377     case 3: /* Get all peers, active addresses */
378       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Run stage 3: \n");
379       phal = GNUNET_ATS_performance_list_addresses (ph,
380                                              NULL,
381                                              GNUNET_NO,
382                                              &all_active_addresses_cb, NULL);
383       GNUNET_assert (NULL != phal);
384       break;
385     default:
386       /* done */
387       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "All tests successful, shutdown... \n");
388       GNUNET_SCHEDULER_add_now (&end, NULL);
389       return;
390   }
391 }
392
393
394 static void
395 address_suggest_cb (void *cls, const struct GNUNET_HELLO_Address *address,
396                     struct Session *session,
397                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_out,
398                     struct GNUNET_BANDWIDTH_Value32NBO bandwidth_in,
399                     const struct GNUNET_ATS_Information *ats,
400                     uint32_t ats_count)
401 {
402   static int suggest_p0;
403   static int suggest_p1;
404
405   if (0 == memcmp (&address->peer, &p[0].id,
406                    sizeof (struct GNUNET_PeerIdentity)));
407     suggest_p0++;
408   if (0 == memcmp (&address->peer, &p[1].id,
409                    sizeof (struct GNUNET_PeerIdentity)));
410     suggest_p1++;
411
412   if ((GNUNET_YES >= suggest_p0) && (GNUNET_YES >= suggest_p1))
413   {
414       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have address suggestion for both peers\n");
415       test_performance_api(NULL, NULL);
416       //GNUNET_SCHEDULER_add_now (&test_performance_api, NULL);
417   }
418 }
419
420
421 static void
422 run (void *cls, 
423      const struct GNUNET_CONFIGURATION_Handle *mycfg,
424      struct GNUNET_TESTING_Peer *peer)
425 {
426   ret = 1;
427   cfg = (struct GNUNET_CONFIGURATION_Handle *) mycfg;
428   die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, NULL);
429
430
431   /* set up peer 0 */
432   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
433                                     &p[0].id.hashPubKey);
434
435   p0_addresses[0].plugin = "test";
436   p0_addresses[0].session = NULL;
437   p0_addresses[0].addr = GNUNET_strdup ("test_p0_a0");
438   p0_addresses[0].addr_len = strlen (p0_addresses[0].addr) + 1;
439
440   p0_ha[0].address = p0_addresses[0].addr;
441   p0_ha[0].address_length = p0_addresses[0].addr_len;
442   p0_ha[0].peer = p[0].id;
443   p0_ha[0].transport_name = p0_addresses[0].plugin;
444
445   p0_addresses[1].plugin = "test";
446   p0_addresses[1].session = NULL;
447   p0_addresses[1].addr = GNUNET_strdup ("test_p0_a1");
448   p0_addresses[1].addr_len = strlen(p0_addresses[1].addr) + 1;
449
450   p0_ha[1].address = p0_addresses[1].addr;
451   p0_ha[1].address_length = p0_addresses[1].addr_len;
452   p0_ha[1].peer = p[0].id;
453   p0_ha[1].transport_name = p0_addresses[1].plugin;
454
455   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer 0: `%s'\n",
456               GNUNET_i2s (&p[0].id));
457
458   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
459                                     &p[1].id.hashPubKey);
460
461   p1_addresses[0].plugin = "test";
462   p1_addresses[0].session = NULL;
463   p1_addresses[0].addr = GNUNET_strdup ("test_p1_a0");
464   p1_addresses[0].addr_len = strlen(p1_addresses[0].addr) + 1;
465
466   p1_ha[0].address = p1_addresses[0].addr;
467   p1_ha[0].address_length = p1_addresses[0].addr_len;
468   p1_ha[0].peer = p[1].id;
469   p1_ha[0].transport_name = p1_addresses[0].plugin;
470
471   p1_addresses[1].plugin = "test";
472   p1_addresses[1].session = NULL;
473   p1_addresses[1].addr = GNUNET_strdup ("test_p1_a1");
474   p1_addresses[1].addr_len = strlen(p1_addresses[1].addr) + 1;
475
476   p1_ha[1].address = p1_addresses[1].addr;
477   p1_ha[1].address_length = p1_addresses[1].addr_len;
478   p1_ha[1].peer = p[1].id;
479   p1_ha[1].transport_name = p1_addresses[1].plugin;
480
481
482   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created peer 1: `%s'\n",
483               GNUNET_i2s (&p[1].id));
484
485
486   /* Add addresses */
487   ats = GNUNET_ATS_scheduling_init (cfg, &address_suggest_cb, NULL);
488   if (ats == NULL)
489   {
490     ret = GNUNET_SYSERR;
491     end ();
492     return;
493   }
494
495   GNUNET_ATS_address_add (ats, &p0_ha[0], NULL, NULL, 0);
496   GNUNET_ATS_address_add (ats, &p0_ha[1], NULL, NULL, 0);
497
498   GNUNET_ATS_address_add (ats, &p1_ha[0], NULL, NULL, 0);
499   GNUNET_ATS_address_add (ats, &p1_ha[1], NULL, NULL, 0);
500
501   //GNUNET_ATS_address_in_use (ats, &p0_ha[0], NULL, GNUNET_YES);
502   //GNUNET_ATS_address_in_use (ats, &p1_ha[1], NULL, GNUNET_YES);
503
504   GNUNET_ATS_suggest_address (ats, &p[0].id);
505   GNUNET_ATS_suggest_address (ats, &p[1].id);
506 }
507
508
509 int
510 main (int argc, char *argv[])
511 {
512   if (0 != GNUNET_TESTING_peer_run ("test_ats_api_performance",
513                                     "test_ats_api.conf",
514                                     &run, NULL))
515     return 1;
516   return ret;
517 }
518
519 /* end of file test_ats_api_performance.c */