-fixes
[oweals/gnunet.git] / src / fs / test_fs_download_recursive.c
1 /*
2      This file is part of GNUnet.
3      (C) 2004, 2005, 2006, 2008 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 /**
22  * @file applications/fs/fsui/recursive_download_test.c
23  * @brief testcase for fsui recursive upload-download
24  * @author Christian Grothoff
25  * @author Heikki Lindholm
26  */
27
28 #include "platform.h"
29 #include "gnunet_util.h"
30 #include "gnunet_fsui_lib.h"
31
32 #define DEBUG_VERBOSE GNUNET_NO
33
34 #define CHECK(a) if (!(a)) { ok = GNUNET_NO; GNUNET_GE_BREAK(ectx, 0); goto FAILURE; }
35
36 #define FILESIZE (1024 * 1024 * 2)
37 /* depth-first directory tree d=dir f=file .=end of level*/
38 #define DIRECTORY_TREE_SPEC "dddf.f.d"
39
40 static struct GNUNET_GE_Context *ectx;
41
42 static int download_done;
43
44 static char *
45 makeName (unsigned int i)
46 {
47   char *fn;
48
49   fn = GNUNET_malloc (strlen
50                       ("/tmp/gnunet-fsui-recursive_download_test/FSUITEST") +
51                       15);
52   GNUNET_snprintf (fn,
53                    strlen ("/tmp/gnunet-fsui-recursive_download_test/FSUITEST")
54                    + 15, "/tmp/gnunet-fsui-recursive_download_test/FSUITEST%u/",
55                    i);
56   return fn;
57 }
58
59 static int
60 makeHierarchyHelper (const char *current, const char *tree, int index,
61                      int check)
62 {
63   unsigned int fi, i;
64   int done;
65   char *s, *buf;
66
67   fi = 0;
68   done = 0;
69   while (!done && tree[index] != '\0')
70   {
71     s = GNUNET_malloc (strlen (current) + strlen (DIR_SEPARATOR_STR) + 14);
72     GNUNET_snprintf (s, strlen (current) + strlen (DIR_SEPARATOR_STR) + 14,
73                      "%s%s%u", current, DIR_SEPARATOR_STR, fi);
74     switch (tree[index++])
75     {
76     case 'd':
77       if (check)
78       {
79         if (GNUNET_disk_directory_test (NULL, s) == GNUNET_NO)
80         {
81           index = -1;
82           done = 1;
83         }
84       }
85       else
86       {
87         GNUNET_disk_directory_create (NULL, s);
88       }
89       if (!done)
90         index = makeHierarchyHelper (s, tree, index, check);
91       break;
92     case 'f':
93       if (check)
94       {
95         /* TODO: compare file contents */
96         if (GNUNET_disk_directory_test (NULL, s) != GNUNET_NO)
97         {
98           index = -1;
99           done = 1;
100         }
101       }
102       else
103       {
104         buf = GNUNET_malloc (FILESIZE);
105         for (i = 0; i < FILESIZE; i++)
106           buf[i] = GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 256);
107         GNUNET_disk_file_write (ectx, s, buf, FILESIZE, "600");
108         GNUNET_free (buf);
109       }
110       break;
111     case '.':
112       done = 1;
113       break;
114     default:
115       break;
116     }
117     GNUNET_free (s);
118     fi++;
119   }
120   return index;
121 }
122
123 static char *
124 makeHierarchy (unsigned int i, const char *tree)
125 {
126   char *fn;
127
128   fn = makeName (i);
129   makeHierarchyHelper (fn, tree, 0, 0);
130   return fn;
131 }
132
133 static int
134 checkHierarchy (unsigned int i, const char *tree)
135 {
136   char *fn;
137   int res;
138
139   fn = makeName (i);
140   if (GNUNET_disk_directory_test (NULL, fn) != GNUNET_YES)
141   {
142     GNUNET_free (fn);
143     return GNUNET_SYSERR;
144   }
145   res =
146       ((makeHierarchyHelper (fn, tree, 0, 1) ==
147         -1) ? GNUNET_SYSERR : GNUNET_OK);
148   GNUNET_free (fn);
149   return res;
150 }
151
152
153 static enum GNUNET_FSUI_EventType lastEvent;
154 static enum GNUNET_FSUI_EventType waitForEvent;
155 static struct GNUNET_FSUI_Context *ctx;
156 static struct GNUNET_ECRS_URI *upURI;
157 static struct GNUNET_FSUI_DownloadList *download;
158
159 static void *
160 eventCallback (void *cls, const GNUNET_FSUI_Event * event)
161 {
162   switch (event->type)
163   {
164   case GNUNET_FSUI_download_suspended:
165     download = NULL;
166     break;
167   case GNUNET_FSUI_download_resumed:
168     download = event->data.DownloadResumed.dc.pos;
169     break;
170     break;
171   case GNUNET_FSUI_upload_progress:
172 #if DEBUG_VERBOSE > 1
173     printf ("Upload is progressing (%llu/%llu)...\n",
174             event->data.UploadProgress.completed,
175             event->data.UploadProgress.total);
176 #endif
177     break;
178   case GNUNET_FSUI_upload_completed:
179     upURI = GNUNET_ECRS_uri_duplicate (event->data.UploadCompleted.uri);
180 #if DEBUG_VERBOSE
181     printf ("Upload of `%s' complete.\n", event->data.UploadCompleted.filename);
182 #endif
183     break;
184   case GNUNET_FSUI_download_completed:
185 #if DEBUG_VERBOSE
186     printf ("Download of `%s' complete.\n",
187             event->data.DownloadCompleted.filename);
188 #endif
189     if (checkHierarchy (43, DIRECTORY_TREE_SPEC) == GNUNET_OK)
190       download_done = 1;
191 #if DEBUG_VERBOSE
192     else
193       printf ("Hierarchy check not successful yet...\n");
194 #endif
195     break;
196   case GNUNET_FSUI_download_progress:
197 #if DEBUG_VERBOSE > 1
198     printf ("Download is progressing (%llu/%llu)...\n",
199             event->data.DownloadProgress.completed,
200             event->data.DownloadProgress.total);
201 #endif
202     break;
203   case GNUNET_FSUI_unindex_progress:
204 #if DEBUG_VERBOSE > 1
205     printf ("Unindex is progressing (%llu/%llu)...\n",
206             event->data.UnindexProgress.completed,
207             event->data.UnindexProgress.total);
208 #endif
209     break;
210   case GNUNET_FSUI_unindex_completed:
211 #if DEBUG_VERBOSE
212     printf ("Unindex complete.\n");
213 #endif
214     break;
215   case GNUNET_FSUI_unindex_error:
216     FPRINTF (stderr, "Error unindexing: %s\n",
217              event->data.UnindexError.message);
218     break;
219   case GNUNET_FSUI_upload_error:
220     FPRINTF (stderr, "Error uploading: %s\n", event->data.UploadError.message);
221     break;
222   case GNUNET_FSUI_download_error:
223     FPRINTF (stderr, "Error downloading: %s\n",
224              event->data.DownloadError.message);
225     break;
226   case GNUNET_FSUI_download_aborted:
227 #if DEBUG_VERBOSE
228     printf ("Received download aborted event.\n");
229 #endif
230     break;
231   case GNUNET_FSUI_unindex_suspended:
232   case GNUNET_FSUI_upload_suspended:
233   case GNUNET_FSUI_upload_started:
234   case GNUNET_FSUI_upload_stopped:
235   case GNUNET_FSUI_download_started:
236   case GNUNET_FSUI_download_stopped:
237   case GNUNET_FSUI_unindex_started:
238   case GNUNET_FSUI_unindex_stopped:
239     break;
240   default:
241     printf ("Unexpected event: %d\n", event->type);
242     break;
243   }
244   if (lastEvent == waitForEvent)
245     return NULL;                /* ignore all other events */
246   lastEvent = event->type;
247   return NULL;
248 }
249
250
251 #define START_DAEMON 1
252
253 int
254 main (int argc, char *argv[])
255 {
256 #if START_DAEMON
257   struct GNUNET_OS_Process *daemon;
258 #endif
259   int ok;
260   char *fn = NULL;
261   char *fn43 = NULL;
262
263   char *keywords[] = {
264     "down_foo",
265     "down_bar",
266   };
267   int prog;
268   struct GNUNET_MetaData *meta = NULL;
269   struct GNUNET_ECRS_URI *kuri = NULL;
270   struct GNUNET_GC_Configuration *cfg;
271   struct GNUNET_FSUI_UploadList *upload = NULL;
272
273   ok = GNUNET_YES;
274   cfg = GNUNET_GC_create ();
275   if (-1 == GNUNET_GC_parse_configuration (cfg, "check.conf"))
276   {
277     GNUNET_GC_free (cfg);
278     return -1;
279   }
280   FPRINTF (stderr, "%s",  "Setup...\n");
281 #if START_DAEMON
282   GNUNET_disk_directory_remove (NULL,
283                                 "/tmp/gnunet-fsui-recursive_download_test/");
284   daemon = GNUNET_daemon_start (NULL, cfg, "peer.conf", GNUNET_NO);
285   GNUNET_GE_ASSERT (NULL, daemon != NULL);
286   CHECK (GNUNET_OK ==
287          GNUNET_wait_for_daemon_running (NULL, cfg, 30 * GNUNET_CRON_SECONDS));
288   GNUNET_thread_sleep (5 * GNUNET_CRON_SECONDS);        /* give apps time to start */
289   /* ACTUAL TEST CODE */
290 #endif
291   ctx =
292       GNUNET_FSUI_start (NULL, cfg, "fsuirecursive_download_test", 32,
293                          GNUNET_YES, &eventCallback, NULL);
294   CHECK (ctx != NULL);
295   fn = makeHierarchy (42, DIRECTORY_TREE_SPEC);
296   meta = GNUNET_meta_data_create ();
297   kuri =
298       GNUNET_ECRS_keyword_command_line_to_uri (ectx, 2,
299                                                (const char **) keywords);
300   FPRINTF (stderr, "%s",  "Uploading...\n");
301   waitForEvent = GNUNET_FSUI_upload_completed;
302   upload =
303       GNUNET_FSUI_upload_start (ctx, fn,
304                                 (GNUNET_FSUI_DirectoryScanCallback) &
305                                 GNUNET_disk_directory_scan, NULL, 0, 0,
306                                 GNUNET_YES, GNUNET_NO, GNUNET_NO,
307                                 GNUNET_get_time () + 5 * GNUNET_CRON_HOURS,
308                                 meta, kuri, kuri);
309   CHECK (upload != NULL);
310   GNUNET_ECRS_uri_destroy (kuri);
311   kuri = NULL;
312   prog = 0;
313   while (lastEvent != GNUNET_FSUI_upload_completed)
314   {
315     prog++;
316     CHECK (prog < 5000);
317     GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
318     if (GNUNET_shutdown_test () == GNUNET_YES)
319       break;
320   }
321   GNUNET_FSUI_upload_stop (upload);
322   upload = NULL;
323   CHECK (upURI != NULL);
324
325   FPRINTF (stderr, "%s",  "Downloading...\n");
326   waitForEvent = GNUNET_FSUI_download_completed;
327   fn43 = makeName (43);
328   download =
329       GNUNET_FSUI_download_start (ctx, 0, GNUNET_YES, upURI, meta, fn43, NULL,
330                                   NULL);
331   CHECK (download != NULL);
332   GNUNET_free (fn43);
333   fn43 = NULL;
334   prog = 0;
335   while (!download_done)
336   {
337     prog++;
338     CHECK (prog < 5000);
339     GNUNET_thread_sleep (50 * GNUNET_CRON_MILLISECONDS);
340     if (GNUNET_shutdown_test () == GNUNET_YES)
341       break;
342   }
343 FAILURE:
344   FPRINTF (stderr, "%s",  "Cleanup...\n");
345   if (meta != NULL)
346     GNUNET_meta_data_destroy (meta);
347   if (ctx != NULL)
348   {
349     if (download != NULL)
350       GNUNET_FSUI_download_stop (download);
351     GNUNET_FSUI_stop (ctx);
352   }
353   if (fn != NULL)
354   {
355     GNUNET_disk_directory_remove (NULL, fn);
356     GNUNET_free (fn);
357   }
358   if (kuri != NULL)
359     GNUNET_ECRS_uri_destroy (kuri);
360   fn43 = makeName (43);
361   GNUNET_disk_directory_remove (NULL, fn43);
362   GNUNET_free (fn43);
363   if (upURI != NULL)
364     GNUNET_ECRS_uri_destroy (upURI);
365
366 #if START_DAEMON
367   GNUNET_GE_BREAK (NULL, GNUNET_OK == GNUNET_daemon_stop (NULL, daemon));
368   GNUNET_OS_process_close (daemon);
369   daemon = NULL;
370 #endif
371   GNUNET_GC_free (cfg);
372   return (ok == GNUNET_YES) ? 0 : 1;
373 }
374
375 /* end of recursive_download_test.c */