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