fix bad free
[oweals/gnunet.git] / src / testbed-logger / test_testbed_logger_api.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2008--2013 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 testbed-logger/test_testbed_logger_api.c
20  * @brief testcases for the testbed logger api
21  * @author Sree Harsha Totakura
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25 #include "gnunet_testing_lib.h"
26 #include "gnunet_testbed_logger_service.h"
27
28 /**
29  * Generic logging shortcut
30  */
31 #define LOG(kind,...)                           \
32   GNUNET_log (kind, __VA_ARGS__)
33
34 /**
35  * Relative time seconds shorthand
36  */
37 #define TIME_REL_SECS(sec) \
38   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
39
40 /**
41  * Opaque handle for the logging service
42  */
43 static struct GNUNET_TESTBED_LOGGER_Handle *h;
44
45 static struct GNUNET_TESTING_Peer *peer;
46
47 static char *search_dir;
48
49 /**
50  * Abort task identifier
51  */
52 static struct GNUNET_SCHEDULER_Task *abort_task;
53 static struct GNUNET_SCHEDULER_Task *write_task;
54
55 static int result;
56
57 #define CANCEL_TASK(task) do {                  \
58     if (NULL != task) \
59     {                                           \
60       GNUNET_SCHEDULER_cancel (task);     \
61       task = NULL;    \
62     }                                           \
63   } while (0)
64
65 /**
66  * shortcut to exit during failure
67  */
68 #define FAIL_TEST(cond, ret) do {                               \
69     if (!(cond)) {                                              \
70       GNUNET_break(0);                                          \
71       CANCEL_TASK (abort_task);                                 \
72       abort_task = GNUNET_SCHEDULER_add_now (&do_abort, NULL);  \
73       ret;                                                      \
74     }                                                           \
75   } while (0)
76
77
78 /**
79  * Shutdown nicely
80  *
81  * @param cls NULL
82  * @param tc the task context
83  */
84 static void
85 shutdown_now ()
86 {
87   CANCEL_TASK (abort_task);
88   CANCEL_TASK (write_task);
89   GNUNET_free_non_null (search_dir);
90   if (NULL != h)
91     GNUNET_TESTBED_LOGGER_disconnect (h);
92   GNUNET_SCHEDULER_shutdown ();
93 }
94
95
96 static void
97 do_abort (void *cls)
98 {
99   LOG (GNUNET_ERROR_TYPE_WARNING,
100        "Aborting\n");
101   abort_task = NULL;
102   shutdown_now ();
103 }
104
105
106 #define BSIZE 1024
107
108
109 /**
110  * Function called to iterate over a directory.
111  *
112  * @param cls closure
113  * @param filename complete filename (absolute path)
114  * @return #GNUNET_OK to continue to iterate,
115  *  #GNUNET_NO to stop iteration with no error,
116  *  #GNUNET_SYSERR to abort iteration with error!
117  */
118 static int
119 iterator_cb (void *cls,
120              const char *filename)
121 {
122   const char *fn;
123   size_t len;
124   uint64_t fs;
125
126   LOG (GNUNET_ERROR_TYPE_DEBUG,
127        "Iterator sees file %s\n",
128        filename);
129   len = strlen (filename);
130   fn = filename + len;
131   if (0 != strcasecmp (".dat", fn - 4))
132     return GNUNET_OK;
133   if (GNUNET_OK !=
134       GNUNET_DISK_file_size (filename,
135                              &fs,
136                              GNUNET_NO,
137                              GNUNET_YES))
138   {
139     LOG (GNUNET_ERROR_TYPE_DEBUG,
140          "Failed to obtain file size for file %s\n",
141          filename);
142     return GNUNET_SYSERR;
143   }
144   if ((BSIZE * 2) != fs)
145   {
146     LOG (GNUNET_ERROR_TYPE_DEBUG,
147          "Unexpected file size for file %s\n",
148          filename);
149     /* The file size should be equal to what we
150        have written */
151     return GNUNET_SYSERR;
152   }
153   result = GNUNET_OK;
154   return GNUNET_OK;
155 }
156
157
158 /**
159  * Functions of this type are called to notify a successful
160  * transmission of the message to the logger service
161  *
162  * @param cls the closure given to GNUNET_TESTBED_LOGGER_send()
163  * @param size the amount of data sent
164  */
165 static void
166 flush_comp (void *cls,
167             size_t size)
168 {
169   LOG (GNUNET_ERROR_TYPE_DEBUG,
170        "Flush running\n");
171   FAIL_TEST (&write_task == cls,
172              return);
173   FAIL_TEST ((BSIZE * 2) == size,
174              return);
175   FAIL_TEST (GNUNET_OK ==
176              GNUNET_TESTING_peer_stop (peer),
177              return);
178   LOG (GNUNET_ERROR_TYPE_DEBUG,
179        "Peer stopped, scanning %s\n",
180        search_dir);
181   FAIL_TEST (GNUNET_SYSERR !=
182              GNUNET_DISK_directory_scan (search_dir,
183                                          &iterator_cb,
184                                          NULL),
185              return);
186   shutdown_now ();
187 }
188
189
190 static void
191 do_write (void *cls)
192 {
193   static int i;
194   char buf[BSIZE];
195
196   write_task = NULL;
197   LOG (GNUNET_ERROR_TYPE_DEBUG,
198        "Write task running\n");
199   if (0 == i)
200     write_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS(1),
201                                                &do_write,
202                                                NULL);
203   (void) memset (buf, i, BSIZE);
204   GNUNET_TESTBED_LOGGER_write (h,
205                                buf,
206                                BSIZE);
207   if (0 == i++)
208     return;
209   GNUNET_TESTBED_LOGGER_flush (h,
210                                &flush_comp,
211                                &write_task);
212 }
213
214
215 /**
216  * Signature of the 'main' function for a (single-peer) testcase that
217  * is run using #GNUNET_TESTING_peer_run().
218  *
219  * @param cls closure
220  * @param cfg configuration of the peer that was started
221  * @param peer identity of the peer that was created
222  */
223 static void
224 test_main (void *cls,
225            const struct GNUNET_CONFIGURATION_Handle *cfg,
226            struct GNUNET_TESTING_Peer *p)
227 {
228   LOG (GNUNET_ERROR_TYPE_DEBUG,
229        "Connecting to logger\n");
230   FAIL_TEST (NULL != (h = GNUNET_TESTBED_LOGGER_connect (cfg)),
231              return);
232   FAIL_TEST (GNUNET_OK ==
233              GNUNET_CONFIGURATION_get_value_filename (cfg,
234                                                       "testbed-logger",
235                                                       "dir",
236                                                       &search_dir),
237              return);
238   peer = p;
239   write_task = GNUNET_SCHEDULER_add_now (&do_write,
240                                          NULL);
241   abort_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (10),
242                                              &do_abort,
243                                              NULL);
244 }
245
246
247 /**
248  * Main function
249  */
250 int
251 main (int argc, char **argv)
252 {
253   int ret;
254
255   result = GNUNET_SYSERR;
256   GNUNET_log_setup ("test-testbed-logger-api",
257                     "WARNING",
258                     NULL);
259   GNUNET_break (GNUNET_OK ==
260                 GNUNET_DISK_directory_remove ("/tmp/test-testbed"));
261   ret = GNUNET_TESTING_service_run ("test-testbed-logger",
262                                     "testbed-logger",
263                                     "test_testbed_logger_api.conf",
264                                     &test_main,
265                                     NULL);
266   GNUNET_break (GNUNET_OK ==
267                 GNUNET_DISK_directory_remove ("/tmp/test-testbed"));
268   if (0 != ret)
269     return 1;
270   if (GNUNET_OK != result)
271     return 2;
272   return 0;
273 }