-Merge branch 'master' of ssh://gnunet.org/gnunet into gsoc2018/rest_api
[oweals/gnunet.git] / src / transport / test_quota_compliance.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 2011, 2016 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 /**
19  * @file transport/test_quota_compliance.c
20  * @brief base test case for transport implementations
21  *
22  * This test case tests quota compliance both on transport level
23  */
24 #include "platform.h"
25 #include "gnunet_transport_service.h"
26 #include "gnunet_ats_service.h"
27 #include "gauger.h"
28 #include "transport-testing.h"
29
30 /**
31  * Testcase timeout
32  */
33 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 480)
34
35 #define DURATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 80)
36
37
38 static struct GNUNET_SCHEDULER_Task *measure_task;
39
40 static char *gen_cfgs[2];
41
42 static unsigned long long quota_in[] = { 10000, 10000 };
43
44 static unsigned long long quota_out[] = { 10000, 10000 };
45
46 static struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext *ccc;
47
48
49 /**
50  * Note that this value must not significantly exceed
51  * 'MAX_PENDING' in 'gnunet-service-transport.c', otherwise
52  * messages may be dropped even for a reliable transport.
53  */
54 #define TOTAL_MSGS (1024 * 32)
55
56 static unsigned long long total_bytes_recv;
57
58 static struct GNUNET_TIME_Absolute start_time;
59
60
61 static void
62 report ()
63 {
64   unsigned long long delta;
65   unsigned long long datarate;
66
67   delta = GNUNET_TIME_absolute_get_duration (start_time).rel_value_us;
68   datarate = (total_bytes_recv * 1000 * 1000) / delta;
69
70   FPRINTF (stderr,
71            "Throughput was %llu b/s\n",
72            datarate);
73   ccc->global_ret = GNUNET_OK;
74   if (datarate > 1.5 * quota_in[1])
75   {
76     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
77                 "Datarate of %llu b/s significantly higher than allowed inbound quota of %llu b/s\n",
78                 datarate,
79                 quota_in[1]);
80     ccc->global_ret = GNUNET_SYSERR;
81   }
82   if (datarate > 1.5 * quota_out[0])
83   {
84     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
85                 "Datarate of %llu b/s significantly higher than allowed outbound quota of %llu b/s\n",
86                 datarate,
87                 quota_out[0]);
88     ccc->global_ret = GNUNET_SYSERR;
89   }
90   if (GNUNET_OK == ccc->global_ret)
91   {
92     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
93                 "Datarate of %llu b/s complied to allowed outbound quota of %llu b/s and inbound quota of %llu b/s\n",
94                 datarate,
95                 quota_out[0],
96                 quota_in[1]);
97   }
98 }
99
100
101 static void
102 custom_shutdown (void *cls)
103 {
104   if (NULL != measure_task)
105   {
106     GNUNET_SCHEDULER_cancel (measure_task);
107     measure_task = NULL;
108   }
109   report ();
110 }
111
112
113 static size_t
114 get_size (unsigned int iter)
115 {
116   size_t ret;
117
118   ret = (iter * iter * iter) % 60000;
119   ret += sizeof (struct GNUNET_TRANSPORT_TESTING_TestMessage);
120   return ret;
121 }
122
123
124 static void
125 notify_receive (void *cls,
126                 struct GNUNET_TRANSPORT_TESTING_PeerContext *receiver,
127                 const struct GNUNET_PeerIdentity *sender,
128                 const struct GNUNET_TRANSPORT_TESTING_TestMessage *hdr)
129 {
130
131   if (GNUNET_TRANSPORT_TESTING_SIMPLE_MTYPE != ntohs (hdr->header.type))
132     return;
133   total_bytes_recv += ntohs (hdr->header.size);
134
135   {
136     char *ps = GNUNET_strdup (GNUNET_i2s (&receiver->id));
137
138     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
139                 "Peer %u (`%s') got message %u of size %u from peer (`%s')\n",
140                 receiver->no,
141                 ps,
142                 ntohl (hdr->num),
143                 ntohs (hdr->header.size),
144                 GNUNET_i2s (sender));
145     GNUNET_free (ps);
146   }
147 }
148
149
150 static void
151 measure (void *cls)
152 {
153   static int counter;
154
155   measure_task = NULL;
156   counter++;
157   if ((DURATION.rel_value_us / 1000 / 1000LL) < counter)
158   {
159     FPRINTF (stderr, "%s",  ".\n");
160     GNUNET_SCHEDULER_shutdown ();
161     return;
162   }
163   FPRINTF (stderr, "%s",  ".");
164   measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
165                                                &measure,
166                                                NULL);
167 }
168
169
170 static void
171 start_task (void *cls)
172 {
173   static struct GNUNET_TRANSPORT_TESTING_SendClosure sc = {
174     .num_messages = TOTAL_MSGS,
175     .get_size_cb = &get_size
176   };
177
178   sc.ccc = ccc;
179   measure_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
180                                                &measure,
181                                                NULL);
182   start_time = GNUNET_TIME_absolute_get ();
183   GNUNET_SCHEDULER_add_now (&GNUNET_TRANSPORT_TESTING_simple_send,
184                             &sc);
185 }
186
187
188 static char *
189 generate_config (const char *cfg_file,
190                  unsigned long long quota_in,
191                  unsigned long long quota_out)
192 {
193   char *in_name;
194   char *out_name;
195   char *fname = NULL;
196   struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
197
198   GNUNET_assert (GNUNET_OK ==
199                  GNUNET_CONFIGURATION_load (cfg,
200                                             cfg_file));
201   GNUNET_asprintf (&fname,
202                    "q_in_%llu_q_out_%llu_%s",
203                    quota_in,
204                    quota_out,
205                    cfg_file);
206   GNUNET_CONFIGURATION_set_value_string (cfg,
207                                          "PATHS",
208                                          "DEFAULTCONFIG",
209                                          fname);
210   for (int c = 0; c < GNUNET_ATS_NetworkTypeCount; c++)
211   {
212     GNUNET_asprintf (&in_name,
213                      "%s_QUOTA_IN",
214                      GNUNET_ATS_print_network_type (c));
215     GNUNET_asprintf (&out_name,
216                      "%s_QUOTA_OUT",
217                      GNUNET_ATS_print_network_type (c));
218     GNUNET_CONFIGURATION_set_value_number (cfg,
219                                            "ats",
220                                            in_name,
221                                            quota_in);
222     GNUNET_CONFIGURATION_set_value_number (cfg,
223                                            "ats",
224                                            out_name,
225                                            quota_out);
226     GNUNET_free (in_name);
227     GNUNET_free (out_name);
228   }
229   GNUNET_assert (GNUNET_OK ==
230                  GNUNET_CONFIGURATION_write (cfg,
231                                              fname));
232   GNUNET_CONFIGURATION_destroy (cfg);
233   return fname;
234 }
235
236
237 static int
238 check (void *cls,
239        struct GNUNET_TRANSPORT_TESTING_Handle *tth_,
240        const char *test_plugin_,
241        const char *test_name_,
242        unsigned int num_peers,
243        char *cfg_files[])
244 {
245   struct GNUNET_TRANSPORT_TESTING_ConnectCheckContext my_ccc = {
246     .connect_continuation = &start_task,
247     .config_file = "test_quota_compliance_data.conf",
248     .rec = &notify_receive,
249     .nc = &GNUNET_TRANSPORT_TESTING_log_connect,
250     .nd = &GNUNET_TRANSPORT_TESTING_log_disconnect,
251     .shutdown_task = &custom_shutdown,
252     .timeout = TIMEOUT
253   };
254   ccc = &my_ccc;
255
256   if (NULL != strstr (test_name_,
257                       "asymmetric"))
258   {
259     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
260                 "Running asymmetric test with sending peer unlimited, receiving peer (in/out): %llu/%llu b/s \n",
261                 quota_in[1],
262                 quota_out[1]);
263     quota_out[0] = 1024 * 1024 * 1024;
264     quota_in[0] = 1024 * 1024 * 1024;
265   }
266   else
267   {
268     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
269                 "Running symmetric test with (in/out) %llu/%llu b/s \n",
270                 quota_in[1],
271                 quota_out[1]);
272   }
273   for (unsigned int i=0;i<2;i++)
274   {
275     gen_cfgs[i] = generate_config (cfg_files[i],
276                                    quota_in[i],
277                                    quota_out[i]);
278     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
279                 "Generated config file `%s'\n",
280                 gen_cfgs[i]);
281   }
282
283   return GNUNET_TRANSPORT_TESTING_connect_check (&my_ccc,
284                                                  tth_,
285                                                  test_plugin_,
286                                                  test_name_,
287                                                  num_peers,
288                                                  gen_cfgs);
289 }
290
291
292 int
293 main (int argc,
294       char *argv[])
295 {
296   if (GNUNET_OK !=
297       GNUNET_TRANSPORT_TESTING_main (2,
298                                      &check,
299                                      NULL))
300   {
301     GNUNET_break (0);
302     return 1;
303   }
304   for (unsigned int i=0;i<2;i++)
305   {
306     if ( (NULL != gen_cfgs[i]) &&
307          (GNUNET_YES == GNUNET_DISK_file_test (gen_cfgs[i])) )
308     {
309       GNUNET_DISK_directory_remove (gen_cfgs[i]);
310       GNUNET_free (gen_cfgs[i]);
311     }
312   }
313   return 0;
314 }
315
316
317 /* end of test_quota_compliance.c */