aboutsummaryrefslogtreecommitdiff
path: root/src/fs/fs_test_lib.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-09-09 13:28:48 +0000
committerChristian Grothoff <christian@grothoff.org>2012-09-09 13:28:48 +0000
commit9d732bb204de9177aad6ae70c910cbf2615d81a3 (patch)
tree44ddd6e9e1dad749db51003acfa46d7835593dc6 /src/fs/fs_test_lib.c
parenta1d7926951beb7466a1462e43b9933530e5825f7 (diff)
downloadgnunet-9d732bb204de9177aad6ae70c910cbf2615d81a3.tar.gz
gnunet-9d732bb204de9177aad6ae70c910cbf2615d81a3.zip
make fs tests build against new testbed library -- they do not pass yet
Diffstat (limited to 'src/fs/fs_test_lib.c')
-rw-r--r--src/fs/fs_test_lib.c892
1 files changed, 404 insertions, 488 deletions
diff --git a/src/fs/fs_test_lib.c b/src/fs/fs_test_lib.c
index 06ab01f8d..bbed98249 100644
--- a/src/fs/fs_test_lib.c
+++ b/src/fs/fs_test_lib.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2010, 2011 Christian Grothoff (and other contributing authors) 3 (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -20,8 +20,8 @@
20 20
21/** 21/**
22 * @file fs/fs_test_lib.c 22 * @file fs/fs_test_lib.c
23 * @brief library routines for testing FS publishing and downloading 23 * @brief library routines for testing FS publishing and downloading;
24 * with multiple peers; this code is limited to flat files 24 * this code is limited to flat files
25 * and no keywords (those functions can be tested with 25 * and no keywords (those functions can be tested with
26 * single-peer setups; this is for testing routing). 26 * single-peer setups; this is for testing routing).
27 * @author Christian Grothoff 27 * @author Christian Grothoff
@@ -29,23 +29,21 @@
29#include "platform.h" 29#include "platform.h"
30#include "fs_api.h" 30#include "fs_api.h"
31#include "fs_test_lib.h" 31#include "fs_test_lib.h"
32#include "gnunet_testing_lib.h"
33 32
34#define CONNECT_ATTEMPTS 4
35 33
36#define CONTENT_LIFETIME GNUNET_TIME_UNIT_HOURS 34#define CONTENT_LIFETIME GNUNET_TIME_UNIT_HOURS
37 35
36
38/** 37/**
39 * Handle for a daemon started for testing FS. 38 * Handle for a publishing operation started for testing FS.
40 */ 39 */
41struct GNUNET_FS_TestDaemon 40struct TestPublishOperation
42{ 41{
43 42
44 /** 43 /**
45 * Global configuration, only stored in first test daemon, 44 * Handle for the operation to connect to the peer's 'fs' service.
46 * otherwise NULL.
47 */ 45 */
48 struct GNUNET_CONFIGURATION_Handle *gcfg; 46 struct GNUNET_TESTBED_Operation *fs_op;
49 47
50 /** 48 /**
51 * Handle to the file sharing context using this daemon. 49 * Handle to the file sharing context using this daemon.
@@ -53,27 +51,6 @@ struct GNUNET_FS_TestDaemon
53 struct GNUNET_FS_Handle *fs; 51 struct GNUNET_FS_Handle *fs;
54 52
55 /** 53 /**
56 * Handle to the daemon via testing.
57 */
58 struct GNUNET_TESTING_Daemon *daemon;
59
60 /**
61 * Note that 'group' will be the same value for all of the
62 * daemons started jointly.
63 */
64 struct GNUNET_TESTING_PeerGroup *group;
65
66 /**
67 * Configuration for accessing this peer.
68 */
69 struct GNUNET_CONFIGURATION_Handle *cfg;
70
71 /**
72 * ID of this peer.
73 */
74 struct GNUNET_PeerIdentity id;
75
76 /**
77 * Function to call when upload is done. 54 * Function to call when upload is done.
78 */ 55 */
79 GNUNET_FS_TEST_UriContinuation publish_cont; 56 GNUNET_FS_TEST_UriContinuation publish_cont;
@@ -109,6 +86,49 @@ struct GNUNET_FS_TestDaemon
109 char *publish_tmp_file; 86 char *publish_tmp_file;
110 87
111 /** 88 /**
89 * Size of the file.
90 */
91 uint64_t size;
92
93 /**
94 * Anonymity level used.
95 */
96 uint32_t anonymity;
97
98 /**
99 * Verbosity level of the current operation.
100 */
101 unsigned int verbose;
102
103 /**
104 * Are we testing indexing? (YES: index, NO: insert, SYSERR: simulate)
105 */
106 int do_index;
107};
108
109
110/**
111 * Handle for a download operation started for testing FS.
112 */
113struct TestDownloadOperation
114{
115
116 /**
117 * Handle for the operation to connect to the peer's 'fs' service.
118 */
119 struct GNUNET_TESTBED_Operation *fs_op;
120
121 /**
122 * Handle to the file sharing context using this daemon.
123 */
124 struct GNUNET_FS_Handle *fs;
125
126 /**
127 * Handle to the daemon via testing.
128 */
129 struct GNUNET_TESTING_Daemon *daemon;
130
131 /**
112 * Function to call when download is done. 132 * Function to call when download is done.
113 */ 133 */
114 GNUNET_SCHEDULER_Task download_cont; 134 GNUNET_SCHEDULER_Task download_cont;
@@ -119,9 +139,9 @@ struct GNUNET_FS_TestDaemon
119 void *download_cont_cls; 139 void *download_cont_cls;
120 140
121 /** 141 /**
122 * Seed for download verification. 142 * URI to download.
123 */ 143 */
124 uint32_t download_seed; 144 struct GNUNET_FS_Uri *uri;
125 145
126 /** 146 /**
127 * Task to abort downloading (timeout). 147 * Task to abort downloading (timeout).
@@ -134,107 +154,108 @@ struct GNUNET_FS_TestDaemon
134 struct GNUNET_FS_DownloadContext *download_context; 154 struct GNUNET_FS_DownloadContext *download_context;
135 155
136 /** 156 /**
137 * Verbosity level of the current operation. 157 * Size of the file.
138 */ 158 */
139 int verbose; 159 uint64_t size;
140 160
161 /**
162 * Anonymity level used.
163 */
164 uint32_t anonymity;
141 165
142}; 166 /**
167 * Seed for download verification.
168 */
169 uint32_t download_seed;
143 170
144/** 171 /**
145 * Check whether peers successfully shut down. 172 * Verbosity level of the current operation.
146 */ 173 */
147static void 174 unsigned int verbose;
148shutdown_callback (void *cls, const char *emsg)
149{
150 struct GNUNET_CONFIGURATION_Handle *gcfg = cls;
151 175
152 if (emsg != NULL) 176};
153 {
154 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Shutdown of peers failed: %s\n",
155 emsg);
156 }
157 else
158 {
159#if VERBOSE
160 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
161#endif
162 }
163 if (gcfg != NULL)
164 GNUNET_CONFIGURATION_destroy (gcfg);
165}
166 177
167 178
179/**
180 * Task scheduled to report on the completion of our publish operation.
181 *
182 * @param cls the publish operation context
183 * @param tc scheduler context (unused)
184 */
168static void 185static void
169report_uri (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 186report_uri (void *cls,
187 const struct GNUNET_SCHEDULER_TaskContext *tc)
170{ 188{
171 struct GNUNET_FS_TestDaemon *daemon = cls; 189 struct TestPublishOperation *po = cls;
172 GNUNET_FS_TEST_UriContinuation cont; 190
173 struct GNUNET_FS_Uri *uri; 191 GNUNET_FS_publish_stop (po->publish_context);
174 192 GNUNET_TESTBED_operation_done (po->fs_op);
175 GNUNET_FS_publish_stop (daemon->publish_context); 193 po->publish_cont (po->publish_cont_cls, po->publish_uri);
176 daemon->publish_context = NULL; 194 GNUNET_FS_uri_destroy (po->publish_uri);
177 cont = daemon->publish_cont; 195 GNUNET_free_non_null (po->publish_tmp_file);
178 daemon->publish_cont = NULL; 196 GNUNET_free (po);
179 uri = daemon->publish_uri;
180 cont (daemon->publish_cont_cls, uri);
181 GNUNET_FS_uri_destroy (uri);
182} 197}
183 198
184 199
200/**
201 * Task scheduled to run when publish operation times out.
202 *
203 * @param cls the publish operation context
204 * @param tc scheduler context (unused)
205 */
185static void 206static void
186report_success (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 207publish_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
187{ 208{
188 struct GNUNET_FS_TestDaemon *daemon = cls; 209 struct TestPublishOperation *po = cls;
189 210
190 GNUNET_FS_download_stop (daemon->download_context, GNUNET_YES); 211 po->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK;
191 daemon->download_context = NULL; 212 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
192 GNUNET_SCHEDULER_add_continuation (daemon->download_cont, 213 "Timeout while trying to publish data\n");
193 daemon->download_cont_cls, 214 if (NULL == po->fs)
194 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 215 GNUNET_TESTBED_operation_cancel (po->fs_op);
195 daemon->download_cont = NULL; 216 else
217 GNUNET_TESTBED_operation_done (po->fs_op);
218 GNUNET_FS_publish_stop (po->publish_context);
219 GNUNET_TESTBED_operation_done (po->fs_op);
220 po->publish_cont (po->publish_cont_cls, NULL);
221 GNUNET_free_non_null (po->publish_tmp_file);
222 GNUNET_free (po);
196} 223}
197 224
198 225
226/**
227 * Progress callback for file-sharing events while publishing.
228 *
229 * @param cls the publish operation context
230 * @param info information about the event
231 */
199static void * 232static void *
200progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) 233publish_progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
201{ 234{
202 struct GNUNET_FS_TestDaemon *daemon = cls; 235 struct TestPublishOperation *po = cls;
203 236
204 switch (info->status) 237 switch (info->status)
205 { 238 {
206 case GNUNET_FS_STATUS_PUBLISH_COMPLETED: 239 case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
207 GNUNET_SCHEDULER_cancel (daemon->publish_timeout_task); 240 GNUNET_SCHEDULER_cancel (po->publish_timeout_task);
208 daemon->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK; 241 po->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK;
209 daemon->publish_uri = 242 po->publish_uri =
210 GNUNET_FS_uri_dup (info->value.publish.specifics.completed.chk_uri); 243 GNUNET_FS_uri_dup (info->value.publish.specifics.completed.chk_uri);
211 GNUNET_SCHEDULER_add_continuation (&report_uri, daemon, 244 GNUNET_SCHEDULER_add_continuation (&report_uri, po,
212 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 245 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
213 break; 246 break;
214 case GNUNET_FS_STATUS_PUBLISH_PROGRESS: 247 case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
215 if (daemon->verbose) 248 if (po->verbose)
216 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Publishing at %llu/%llu bytes\n", 249 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Publishing at %llu/%llu bytes\n",
217 (unsigned long long) info->value.publish.completed, 250 (unsigned long long) info->value.publish.completed,
218 (unsigned long long) info->value.publish.size); 251 (unsigned long long) info->value.publish.size);
219 break; 252 break;
220 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS: 253 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
221 if (daemon->verbose) 254 if (po->verbose)
222 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Download at %llu/%llu bytes\n", 255 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Download at %llu/%llu bytes\n",
223 (unsigned long long) info->value.download.completed, 256 (unsigned long long) info->value.download.completed,
224 (unsigned long long) info->value.download.size); 257 (unsigned long long) info->value.download.size);
225 break; 258 break;
226 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
227 GNUNET_SCHEDULER_cancel (daemon->download_timeout_task);
228 daemon->download_timeout_task = GNUNET_SCHEDULER_NO_TASK;
229 GNUNET_SCHEDULER_add_continuation (&report_success, daemon,
230 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
231 break;
232 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
233 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
234 break;
235 /* FIXME: monitor data correctness during download progress */
236 /* FIXME: do performance reports given sufficient verbosity */
237 /* FIXME: advance timeout task to "immediate" on error */
238 default: 259 default:
239 break; 260 break;
240 } 261 }
@@ -242,460 +263,347 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
242} 263}
243 264
244 265
245struct StartContext 266/**
246{ 267 * Generate test data for publishing test.
247 struct GNUNET_TIME_Relative timeout; 268 *
248 unsigned int total; 269 * @param cls pointer to uint32_t with publishing seed
249 unsigned int have; 270 * @param offset offset to generate data for
250 struct GNUNET_FS_TestDaemon **daemons; 271 * @param max maximum number of bytes to generate
251 GNUNET_SCHEDULER_Task cont; 272 * @param buf where to write generated data
252 void *cont_cls; 273 * @param emsg where to store error message (unused)
253 struct GNUNET_TESTING_PeerGroup *group; 274 * @return number of bytes written to buf
254 struct GNUNET_CONFIGURATION_Handle *cfg; 275 */
255 GNUNET_SCHEDULER_TaskIdentifier timeout_task; 276static size_t
256}; 277file_generator (void *cls,
257 278 uint64_t offset,
258 279 size_t max,
259static void 280 void *buf,
260notify_running (void *cls, const struct GNUNET_PeerIdentity *id, 281 char **emsg)
261 const struct GNUNET_CONFIGURATION_Handle *cfg,
262 struct GNUNET_TESTING_Daemon *d, const char *emsg)
263{ 282{
264 struct StartContext *sctx = cls; 283 uint32_t *publish_seed = cls;
265 unsigned int i; 284 uint64_t pos;
285 uint8_t *cbuf = buf;
286 int mod;
266 287
267 if (emsg != NULL) 288 if (emsg != NULL)
289 *emsg = NULL;
290 if (buf == NULL)
291 return 0;
292 for (pos = 0; pos < 8; pos++)
293 cbuf[pos] = (uint8_t) (offset >> pos * 8);
294 for (pos = 8; pos < max; pos++)
268 { 295 {
269 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start daemon: %s\n"), 296 mod = (255 - (offset / 1024 / 32));
270 emsg); 297 if (mod == 0)
271 return; 298 mod = 1;
272 } 299 cbuf[pos] = (uint8_t) ((offset * (*publish_seed)) % mod);
273 i = 0;
274 while (i < sctx->total)
275 {
276 if (GNUNET_TESTING_daemon_get (sctx->group, i) == d)
277 break;
278 i++;
279 }
280 GNUNET_assert (i < sctx->total);
281 GNUNET_assert (sctx->have < sctx->total);
282 GNUNET_assert (sctx->daemons[i]->cfg == NULL);
283 sctx->daemons[i]->cfg = GNUNET_CONFIGURATION_dup (cfg);
284 sctx->daemons[i]->group = sctx->group;
285 sctx->daemons[i]->daemon = d;
286 sctx->daemons[i]->id = *id;
287 sctx->have++;
288 if (sctx->have == sctx->total)
289 {
290 GNUNET_SCHEDULER_add_continuation (sctx->cont, sctx->cont_cls,
291 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
292 sctx->daemons[0]->gcfg = sctx->cfg;
293 GNUNET_SCHEDULER_cancel (sctx->timeout_task);
294 for (i = 0; i < sctx->total; i++)
295 {
296 sctx->daemons[i]->fs =
297 GNUNET_FS_start (sctx->daemons[i]->cfg, "<tester>", &progress_cb,
298 sctx->daemons[i], GNUNET_FS_FLAGS_NONE,
299 GNUNET_FS_OPTIONS_END);
300 }
301 GNUNET_free (sctx);
302 } 300 }
301 return max;
303} 302}
304 303
305 304
306static void 305/**
307start_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 306 * Connect adapter for publishing operation.
307 *
308 * @param cls the 'struct TestPublishOperation'
309 * @param cfg configuration of the peer to connect to; will be available until
310 * GNUNET_TESTBED_operation_done() is called on the operation returned
311 * from GNUNET_TESTBED_service_connect()
312 * @return service handle to return in 'op_result', NULL on error
313 */
314static void *
315publish_connect_adapter (void *cls,
316 const struct GNUNET_CONFIGURATION_Handle *cfg)
308{ 317{
309 struct StartContext *sctx = cls; 318 struct TestPublishOperation *po = cls;
310 unsigned int i; 319
311 320 return GNUNET_FS_start (cfg,
312 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 321 "fs-test-publish",
313 "Timeout while trying to start daemons\n"); 322 &publish_progress_cb, po,
314 GNUNET_TESTING_daemons_stop (sctx->group, 323 GNUNET_FS_OPTIONS_END);
315 GNUNET_TIME_relative_multiply
316 (GNUNET_TIME_UNIT_SECONDS, 30),
317 &shutdown_callback, NULL);
318 for (i = 0; i < sctx->total; i++)
319 {
320 if (i < sctx->have)
321 GNUNET_CONFIGURATION_destroy (sctx->daemons[i]->cfg);
322 GNUNET_free (sctx->daemons[i]);
323 sctx->daemons[i] = NULL;
324 }
325 GNUNET_CONFIGURATION_destroy (sctx->cfg);
326 GNUNET_SCHEDULER_add_continuation (sctx->cont, sctx->cont_cls,
327 GNUNET_SCHEDULER_REASON_TIMEOUT);
328 GNUNET_free (sctx);
329} 324}
330 325
331 326
332/** 327/**
333 * Start daemons for testing. 328 * Adapter function called to destroy connection to file-sharing service.
334 * 329 *
335 * @param template_cfg_file configuration template to use 330 * @param cls the 'struct GNUNET_FS_Handle'
336 * @param timeout if this operation cannot be completed within the 331 * @param op_result unused (different for publish/download!)
337 * given period, call the continuation with an error code
338 * @param total number of daemons to start
339 * @param daemons array of 'total' entries to be initialized
340 * (array must already be allocated, will be filled)
341 * @param cont function to call when done
342 * @param cont_cls closure for cont
343 */ 332 */
344void 333static void
345GNUNET_FS_TEST_daemons_start (const char *template_cfg_file, 334fs_disconnect_adapter (void *cls,
346 struct GNUNET_TIME_Relative timeout, 335 void *op_result)
347 unsigned int total,
348 struct GNUNET_FS_TestDaemon **daemons,
349 GNUNET_SCHEDULER_Task cont, void *cont_cls)
350{ 336{
351 struct StartContext *sctx; 337 struct GNUNET_FS_Handle *fs = op_result;
352 unsigned int i;
353
354 GNUNET_assert (total > 0);
355 sctx = GNUNET_malloc (sizeof (struct StartContext));
356 sctx->daemons = daemons;
357 sctx->total = total;
358 sctx->cont = cont;
359 sctx->cont_cls = cont_cls;
360 sctx->cfg = GNUNET_CONFIGURATION_create ();
361 if (GNUNET_OK != GNUNET_CONFIGURATION_load (sctx->cfg, template_cfg_file))
362 {
363 GNUNET_break (0);
364 GNUNET_CONFIGURATION_destroy (sctx->cfg);
365 GNUNET_free (sctx);
366 GNUNET_SCHEDULER_add_continuation (cont, cont_cls,
367 GNUNET_SCHEDULER_REASON_TIMEOUT);
368 return;
369 }
370 for (i = 0; i < total; i++)
371 daemons[i] = GNUNET_malloc (sizeof (struct GNUNET_FS_TestDaemon));
372 sctx->group = GNUNET_TESTING_daemons_start (sctx->cfg, total, total, /* Outstanding connections */
373 total, /* Outstanding ssh connections */
374 timeout, NULL, NULL,
375 &notify_running, sctx, NULL, NULL,
376 NULL);
377 sctx->timeout_task =
378 GNUNET_SCHEDULER_add_delayed (timeout, &start_timeout, sctx);
379}
380 338
381 339 GNUNET_FS_stop (fs);
382struct GNUNET_FS_TEST_ConnectContext 340}
383{
384 GNUNET_SCHEDULER_Task cont;
385 void *cont_cls;
386 struct GNUNET_TESTING_ConnectContext *cc;
387};
388 341
389 342
390/** 343/**
391 * Prototype of a function that will be called whenever 344 * Callback to be called when testbed has connected to the fs service
392 * two daemons are connected by the testing library.
393 * 345 *
394 * @param cls closure 346 * @param cls the 'struct TestPublishOperation'
395 * @param first peer id for first daemon 347 * @param op the operation that has been finished
396 * @param second peer id for the second daemon 348 * @param ca_result the 'struct GNUNET_FS_Handle ' (NULL on error)
397 * @param distance distance between the connected peers 349 * @param emsg error message in case the operation has failed; will be NULL if
398 * @param first_cfg config for the first daemon 350 * operation has executed successfully.
399 * @param second_cfg config for the second daemon
400 * @param first_daemon handle for the first daemon
401 * @param second_daemon handle for the second daemon
402 * @param emsg error message (NULL on success)
403 */ 351 */
404static void 352static void
405notify_connection (void *cls, const struct GNUNET_PeerIdentity *first, 353publish_fs_connect_complete_cb (void *cls,
406 const struct GNUNET_PeerIdentity *second, uint32_t distance, 354 struct GNUNET_TESTBED_Operation *op,
407 const struct GNUNET_CONFIGURATION_Handle *first_cfg, 355 void *ca_result,
408 const struct GNUNET_CONFIGURATION_Handle *second_cfg, 356 const char *emsg)
409 struct GNUNET_TESTING_Daemon *first_daemon,
410 struct GNUNET_TESTING_Daemon *second_daemon,
411 const char *emsg)
412{ 357{
413 struct GNUNET_FS_TEST_ConnectContext *cc = cls; 358 struct TestPublishOperation *po = cls;
359 struct GNUNET_FS_FileInformation *fi;
360 struct GNUNET_DISK_FileHandle *fh;
361 char *em;
362 uint64_t off;
363 char buf[DBLOCK_SIZE];
364 size_t bsize;
365 struct GNUNET_FS_BlockOptions bo;
414 366
415 cc->cc = NULL; 367 if (NULL == ca_result)
416 if (emsg != NULL) 368 {
417 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to connect peers: %s\n", 369 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to connect to FS for publishing: %s\n", emsg);
418 emsg); 370 po->publish_cont (po->publish_cont_cls,
419 GNUNET_SCHEDULER_add_continuation (cc->cont, cc->cont_cls, 371 NULL);
420 (emsg != 372 GNUNET_TESTBED_operation_done (po->fs_op);
421 NULL) ? GNUNET_SCHEDULER_REASON_TIMEOUT : 373 GNUNET_free (po);
422 GNUNET_SCHEDULER_REASON_PREREQ_DONE); 374 return;
423 GNUNET_free (cc); 375 }
376 po->fs = ca_result;
377
378 bo.expiration_time = GNUNET_TIME_relative_to_absolute (CONTENT_LIFETIME);
379 bo.anonymity_level = po->anonymity;
380 bo.content_priority = 42;
381 bo.replication_level = 1;
382 if (GNUNET_YES == po->do_index)
383 {
384 po->publish_tmp_file = GNUNET_DISK_mktemp ("fs-test-publish-index");
385 GNUNET_assert (po->publish_tmp_file != NULL);
386 fh = GNUNET_DISK_file_open (po->publish_tmp_file,
387 GNUNET_DISK_OPEN_WRITE |
388 GNUNET_DISK_OPEN_CREATE,
389 GNUNET_DISK_PERM_USER_READ |
390 GNUNET_DISK_PERM_USER_WRITE);
391 GNUNET_assert (NULL != fh);
392 off = 0;
393 while (off < po->size)
394 {
395 bsize = GNUNET_MIN (sizeof (buf), po->size - off);
396 emsg = NULL;
397 GNUNET_assert (bsize == file_generator (&po->publish_seed, off, bsize, buf, &em));
398 GNUNET_assert (em == NULL);
399 GNUNET_assert (bsize == GNUNET_DISK_file_write (fh, buf, bsize));
400 off += bsize;
401 }
402 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
403 fi = GNUNET_FS_file_information_create_from_file (po->fs, po,
404 po->publish_tmp_file,
405 NULL, NULL, po->do_index,
406 &bo);
407 }
408 else
409 {
410 fi = GNUNET_FS_file_information_create_from_reader (po->fs, po,
411 po->size,
412 &file_generator, &po->publish_seed,
413 NULL, NULL,
414 po->do_index, &bo);
415 }
416 po->publish_context =
417 GNUNET_FS_publish_start (po->fs, fi, NULL, NULL, NULL,
418 GNUNET_FS_PUBLISH_OPTION_NONE);
424} 419}
425 420
426 421
427/** 422/**
428 * Connect two daemons for testing. 423 * Publish a file at the given peer.
429 * 424 *
430 * @param daemon1 first daemon to connect 425 * @param peer where to publish
431 * @param daemon2 second first daemon to connect
432 * @param timeout if this operation cannot be completed within the 426 * @param timeout if this operation cannot be completed within the
433 * given period, call the continuation with an error code 427 * given period, call the continuation with an error code
428 * @param anonymity option for publication
429 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
430 * GNUNET_SYSERR for simulation
431 * @param size size of the file to publish
432 * @param seed seed to use for file generation
433 * @param verbose how verbose to be in reporting
434 * @param cont function to call when done 434 * @param cont function to call when done
435 * @param cont_cls closure for cont 435 * @param cont_cls closure for cont
436 */ 436 */
437struct GNUNET_FS_TEST_ConnectContext * 437void
438GNUNET_FS_TEST_daemons_connect (struct GNUNET_FS_TestDaemon *daemon1, 438GNUNET_FS_TEST_publish (struct GNUNET_TESTBED_Peer *peer,
439 struct GNUNET_FS_TestDaemon *daemon2, 439 struct GNUNET_TIME_Relative timeout, uint32_t anonymity,
440 struct GNUNET_TIME_Relative timeout, 440 int do_index, uint64_t size, uint32_t seed,
441 GNUNET_SCHEDULER_Task cont, void *cont_cls) 441 unsigned int verbose,
442 GNUNET_FS_TEST_UriContinuation cont, void *cont_cls)
442{ 443{
443 struct GNUNET_FS_TEST_ConnectContext *ncc; 444 struct TestPublishOperation *po;
444 445
445 ncc = GNUNET_malloc (sizeof (struct GNUNET_FS_TEST_ConnectContext)); 446 po = GNUNET_malloc (sizeof (struct TestPublishOperation));
446 ncc->cont = cont; 447 po->publish_cont = cont;
447 ncc->cont_cls = cont_cls; 448 po->publish_cont_cls = cont_cls;
448 ncc->cc = 449 po->publish_seed = seed;
449 GNUNET_TESTING_daemons_connect (daemon1->daemon, daemon2->daemon, timeout, 450 po->anonymity = anonymity;
450 CONNECT_ATTEMPTS, GNUNET_YES, 451 po->size = size;
451 &notify_connection, ncc); 452 po->verbose = verbose;
452 return ncc; 453 po->do_index = do_index;
454 po->fs_op = GNUNET_TESTBED_service_connect (po,
455 peer,
456 "fs",
457 &publish_fs_connect_complete_cb,
458 po,
459 &publish_connect_adapter,
460 &fs_disconnect_adapter,
461 po);
462 po->publish_timeout_task =
463 GNUNET_SCHEDULER_add_delayed (timeout, &publish_timeout, po);
453} 464}
454 465
455 466
456/** 467/* ************************** download ************************ */
457 * Cancel connect operation.
458 *
459 * @param cc operation to cancel
460 */
461void
462GNUNET_FS_TEST_daemons_connect_cancel (struct GNUNET_FS_TEST_ConnectContext *cc)
463{
464 GNUNET_TESTING_daemons_connect_cancel (cc->cc);
465 GNUNET_free (cc);
466}
467 468
468 469
469/** 470/**
470 * Obtain peer configuration used for testing. 471 * Task scheduled to run when download operation times out.
471 * 472 *
472 * @param daemons array with the daemons 473 * @param cls the download operation context
473 * @param off which configuration to get 474 * @param tc scheduler context (unused)
474 * @return peer configuration
475 */ 475 */
476const struct GNUNET_CONFIGURATION_Handle * 476static void
477GNUNET_FS_TEST_get_configuration (struct GNUNET_FS_TestDaemon **daemons, 477download_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
478 unsigned int off)
479{ 478{
480 return daemons[off]->cfg; 479 struct TestDownloadOperation *dop = cls;
481}
482 480
483/** 481 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
484 * Obtain peer group used for testing. 482 "Timeout while trying to download file\n");
485 * 483 dop->download_timeout_task = GNUNET_SCHEDULER_NO_TASK;
486 * @param daemons array with the daemons (must contain at least one) 484 GNUNET_FS_download_stop (dop->download_context, GNUNET_YES);
487 * @return peer group 485 GNUNET_SCHEDULER_add_continuation (dop->download_cont,
488 */ 486 dop->download_cont_cls,
489struct GNUNET_TESTING_PeerGroup * 487 GNUNET_SCHEDULER_REASON_TIMEOUT);
490GNUNET_FS_TEST_get_group (struct GNUNET_FS_TestDaemon **daemons) 488 if (NULL == dop->fs)
491{ 489 GNUNET_TESTBED_operation_cancel (dop->fs_op);
492 return daemons[0]->group; 490 else
491 GNUNET_TESTBED_operation_done (dop->fs_op);
492 GNUNET_FS_uri_destroy (dop->uri);
493 GNUNET_free (dop);
493} 494}
494 495
495 496
496/** 497/**
497 * Stop daemons used for testing. 498 * Task scheduled to report on the completion of our download operation.
498 * 499 *
499 * @param total number of daemons to stop 500 * @param cls the download operation context
500 * @param daemons array with the daemons (values will be clobbered) 501 * @param tc scheduler context (unused)
501 */ 502 */
502void
503GNUNET_FS_TEST_daemons_stop (unsigned int total,
504 struct GNUNET_FS_TestDaemon **daemons)
505{
506 unsigned int i;
507 struct GNUNET_TESTING_PeerGroup *pg;
508 struct GNUNET_CONFIGURATION_Handle *gcfg;
509 struct GNUNET_FS_TestDaemon *daemon;
510
511 GNUNET_assert (total > 0);
512 GNUNET_assert (daemons[0] != NULL);
513 pg = daemons[0]->group;
514 gcfg = daemons[0]->gcfg;
515 for (i = 0; i < total; i++)
516 {
517 daemon = daemons[i];
518 if (daemon->download_timeout_task != GNUNET_SCHEDULER_NO_TASK)
519 {
520 GNUNET_SCHEDULER_cancel (daemon->download_timeout_task);
521 daemon->download_timeout_task = GNUNET_SCHEDULER_NO_TASK;
522 }
523 if (daemon->publish_timeout_task != GNUNET_SCHEDULER_NO_TASK)
524 {
525 GNUNET_SCHEDULER_cancel (daemon->publish_timeout_task);
526 daemon->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK;
527 }
528 if (NULL != daemon->download_context)
529 {
530 GNUNET_FS_download_stop (daemon->download_context, GNUNET_YES);
531 daemon->download_context = NULL;
532 }
533 if (daemon->fs != NULL)
534 GNUNET_FS_stop (daemon->fs);
535 if (daemon->cfg != NULL)
536 GNUNET_CONFIGURATION_destroy (daemon->cfg);
537 if (NULL != daemon->publish_tmp_file)
538 {
539 GNUNET_break (GNUNET_OK ==
540 GNUNET_DISK_directory_remove (daemon->publish_tmp_file));
541 GNUNET_free (daemon->publish_tmp_file);
542 daemon->publish_tmp_file = NULL;
543 }
544 GNUNET_free (daemon);
545 daemons[i] = NULL;
546 }
547 GNUNET_TESTING_daemons_stop (pg,
548 GNUNET_TIME_relative_multiply
549 (GNUNET_TIME_UNIT_SECONDS, 30),
550 &shutdown_callback, gcfg);
551}
552
553
554static void 503static void
555publish_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 504report_success (void *cls,
505 const struct GNUNET_SCHEDULER_TaskContext *tc)
556{ 506{
557 struct GNUNET_FS_TestDaemon *daemon = cls; 507 struct TestDownloadOperation *dop = cls;
558 GNUNET_FS_TEST_UriContinuation cont;
559 508
560 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 509 GNUNET_FS_download_stop (dop->download_context, GNUNET_YES);
561 "Timeout while trying to publish data\n"); 510 GNUNET_SCHEDULER_add_continuation (dop->download_cont,
562 cont = daemon->publish_cont; 511 dop->download_cont_cls,
563 daemon->publish_timeout_task = GNUNET_SCHEDULER_NO_TASK; 512 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
564 daemon->publish_cont = NULL; 513 GNUNET_TESTBED_operation_done (dop->fs_op);
565 GNUNET_FS_publish_stop (daemon->publish_context); 514 GNUNET_FS_uri_destroy (dop->uri);
566 daemon->publish_context = NULL; 515 GNUNET_free (dop);
567 cont (daemon->publish_cont_cls, NULL);
568} 516}
569 517
570 518
571static size_t 519/**
572file_generator (void *cls, uint64_t offset, size_t max, void *buf, char **emsg) 520 * Progress callback for file-sharing events while downloading.
521 *
522 * @param cls the download operation context
523 * @param info information about the event
524 */
525static void *
526download_progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
573{ 527{
574 struct GNUNET_FS_TestDaemon *daemon = cls; 528 struct TestDownloadOperation *dop = cls;
575 uint64_t pos;
576 uint8_t *cbuf = buf;
577 int mod;
578 529
579 if (emsg != NULL) 530 switch (info->status)
580 *emsg = NULL;
581 if (buf == NULL)
582 return 0;
583 for (pos = 0; pos < 8; pos++)
584 cbuf[pos] = (uint8_t) (offset >> pos * 8);
585 for (pos = 8; pos < max; pos++)
586 { 531 {
587 mod = (255 - (offset / 1024 / 32)); 532 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
588 if (mod == 0) 533 if (dop->verbose)
589 mod = 1; 534 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Download at %llu/%llu bytes\n",
590 cbuf[pos] = (uint8_t) ((offset * daemon->publish_seed) % mod); 535 (unsigned long long) info->value.download.completed,
536 (unsigned long long) info->value.download.size);
537 break;
538 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
539 GNUNET_SCHEDULER_cancel (dop->download_timeout_task);
540 dop->download_timeout_task = GNUNET_SCHEDULER_NO_TASK;
541 GNUNET_SCHEDULER_add_continuation (&report_success, dop,
542 GNUNET_SCHEDULER_REASON_PREREQ_DONE);
543 break;
544 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
545 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
546 break;
547 /* FIXME: monitor data correctness during download progress */
548 /* FIXME: do performance reports given sufficient verbosity */
549 /* FIXME: advance timeout task to "immediate" on error */
550 default:
551 break;
591 } 552 }
592 return max; 553 return NULL;
593} 554}
594 555
595 556
596
597/** 557/**
598 * Publish a file at the given daemon. 558 * Connect adapter for download operation.
599 * 559 *
600 * @param daemon where to publish 560 * @param cls the 'struct TestDownloadOperation'
601 * @param timeout if this operation cannot be completed within the 561 * @param cfg configuration of the peer to connect to; will be available until
602 * given period, call the continuation with an error code 562 * GNUNET_TESTBED_operation_done() is called on the operation returned
603 * @param anonymity option for publication 563 * from GNUNET_TESTBED_service_connect()
604 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion, 564 * @return service handle to return in 'op_result', NULL on error
605 * GNUNET_SYSERR for simulation
606 * @param size size of the file to publish
607 * @param seed seed to use for file generation
608 * @param verbose how verbose to be in reporting
609 * @param cont function to call when done
610 * @param cont_cls closure for cont
611 */ 565 */
612void 566static void *
613GNUNET_FS_TEST_publish (struct GNUNET_FS_TestDaemon *daemon, 567download_connect_adapter (void *cls,
614 struct GNUNET_TIME_Relative timeout, uint32_t anonymity, 568 const struct GNUNET_CONFIGURATION_Handle *cfg)
615 int do_index, uint64_t size, uint32_t seed,
616 unsigned int verbose,
617 GNUNET_FS_TEST_UriContinuation cont, void *cont_cls)
618{ 569{
619 struct GNUNET_FS_FileInformation *fi; 570 struct TestPublishOperation *po = cls;
620 struct GNUNET_DISK_FileHandle *fh; 571
621 char *emsg; 572 return GNUNET_FS_start (cfg,
622 uint64_t off; 573 "fs-test-download",
623 char buf[DBLOCK_SIZE]; 574 &download_progress_cb, po,
624 size_t bsize; 575 GNUNET_FS_OPTIONS_END);
625 struct GNUNET_FS_BlockOptions bo;
626
627 GNUNET_assert (daemon->publish_cont == NULL);
628 daemon->publish_cont = cont;
629 daemon->publish_cont_cls = cont_cls;
630 daemon->publish_seed = seed;
631 daemon->verbose = verbose;
632 bo.expiration_time = GNUNET_TIME_relative_to_absolute (CONTENT_LIFETIME);
633 bo.anonymity_level = anonymity;
634 bo.content_priority = 42;
635 bo.replication_level = 1;
636 if (GNUNET_YES == do_index)
637 {
638 GNUNET_assert (daemon->publish_tmp_file == NULL);
639 daemon->publish_tmp_file = GNUNET_DISK_mktemp ("fs-test-publish-index");
640 GNUNET_assert (daemon->publish_tmp_file != NULL);
641 fh = GNUNET_DISK_file_open (daemon->publish_tmp_file,
642 GNUNET_DISK_OPEN_WRITE |
643 GNUNET_DISK_OPEN_CREATE,
644 GNUNET_DISK_PERM_USER_READ |
645 GNUNET_DISK_PERM_USER_WRITE);
646 GNUNET_assert (NULL != fh);
647 off = 0;
648 while (off < size)
649 {
650 bsize = GNUNET_MIN (sizeof (buf), size - off);
651 emsg = NULL;
652 GNUNET_assert (bsize == file_generator (daemon, off, bsize, buf, &emsg));
653 GNUNET_assert (emsg == NULL);
654 GNUNET_assert (bsize == GNUNET_DISK_file_write (fh, buf, bsize));
655 off += bsize;
656 }
657 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
658 fi = GNUNET_FS_file_information_create_from_file (daemon->fs, daemon,
659 daemon->publish_tmp_file,
660 NULL, NULL, do_index,
661 &bo);
662 }
663 else
664 {
665 fi = GNUNET_FS_file_information_create_from_reader (daemon->fs, daemon,
666 size, &file_generator,
667 daemon, NULL, NULL,
668 do_index, &bo);
669 }
670 daemon->publish_context =
671 GNUNET_FS_publish_start (daemon->fs, fi, NULL, NULL, NULL,
672 GNUNET_FS_PUBLISH_OPTION_NONE);
673 daemon->publish_timeout_task =
674 GNUNET_SCHEDULER_add_delayed (timeout, &publish_timeout, daemon);
675} 576}
676 577
677 578
579/**
580 * Callback to be called when testbed has connected to the fs service
581 *
582 * @param cls the 'struct TestPublishOperation'
583 * @param op the operation that has been finished
584 * @param ca_result the 'struct GNUNET_FS_Handle ' (NULL on error)
585 * @param emsg error message in case the operation has failed; will be NULL if
586 * operation has executed successfully.
587 */
678static void 588static void
679download_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) 589download_fs_connect_complete_cb (void *cls,
590 struct GNUNET_TESTBED_Operation *op,
591 void *ca_result,
592 const char *emsg)
680{ 593{
681 struct GNUNET_FS_TestDaemon *daemon = cls; 594 struct TestDownloadOperation *dop = cls;
682 595
683 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 596 dop->download_context =
684 "Timeout while trying to download file\n"); 597 GNUNET_FS_download_start (dop->fs, dop->uri, NULL, NULL, NULL, 0, dop->size,
685 daemon->download_timeout_task = GNUNET_SCHEDULER_NO_TASK; 598 dop->anonymity, GNUNET_FS_DOWNLOAD_OPTION_NONE,
686 GNUNET_FS_download_stop (daemon->download_context, GNUNET_YES); 599 NULL, NULL);
687 daemon->download_context = NULL;
688 GNUNET_SCHEDULER_add_continuation (daemon->download_cont,
689 daemon->download_cont_cls,
690 GNUNET_SCHEDULER_REASON_TIMEOUT);
691 daemon->download_cont = NULL;
692} 600}
693 601
694 602
695/** 603/**
696 * Perform test download. 604 * Perform test download.
697 * 605 *
698 * @param daemon which peer to download from 606 * @param peer which peer to download from
699 * @param timeout if this operation cannot be completed within the 607 * @param timeout if this operation cannot be completed within the
700 * given period, call the continuation with an error code 608 * given period, call the continuation with an error code
701 * @param anonymity option for download 609 * @param anonymity option for download
@@ -706,26 +614,34 @@ download_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
706 * @param cont_cls closure for cont 614 * @param cont_cls closure for cont
707 */ 615 */
708void 616void
709GNUNET_FS_TEST_download (struct GNUNET_FS_TestDaemon *daemon, 617GNUNET_FS_TEST_download (struct GNUNET_TESTBED_Peer *peer,
710 struct GNUNET_TIME_Relative timeout, 618 struct GNUNET_TIME_Relative timeout,
711 uint32_t anonymity, uint32_t seed, 619 uint32_t anonymity, uint32_t seed,
712 const struct GNUNET_FS_Uri *uri, unsigned int verbose, 620 const struct GNUNET_FS_Uri *uri, unsigned int verbose,
713 GNUNET_SCHEDULER_Task cont, void *cont_cls) 621 GNUNET_SCHEDULER_Task cont, void *cont_cls)
714{ 622{
715 uint64_t size; 623 struct TestDownloadOperation *dop;
716 624
717 GNUNET_assert (daemon->download_cont == NULL); 625 dop = GNUNET_malloc (sizeof (struct TestDownloadOperation));
718 size = GNUNET_FS_uri_chk_get_file_size (uri); 626 dop->uri = GNUNET_FS_uri_dup (uri);
719 daemon->verbose = verbose; 627 dop->size = GNUNET_FS_uri_chk_get_file_size (uri);
720 daemon->download_cont = cont; 628 dop->verbose = verbose;
721 daemon->download_cont_cls = cont_cls; 629 dop->anonymity = anonymity;
722 daemon->download_seed = seed; 630 dop->download_cont = cont;
723 daemon->download_context = 631 dop->download_cont_cls = cont_cls;
724 GNUNET_FS_download_start (daemon->fs, uri, NULL, NULL, NULL, 0, size, 632 dop->download_seed = seed;
725 anonymity, GNUNET_FS_DOWNLOAD_OPTION_NONE, NULL, 633
726 NULL); 634 dop->fs_op = GNUNET_TESTBED_service_connect (dop,
727 daemon->download_timeout_task = 635 peer,
728 GNUNET_SCHEDULER_add_delayed (timeout, &download_timeout, daemon); 636 "fs",
637 &download_fs_connect_complete_cb,
638 dop,
639 &download_connect_adapter,
640 &fs_disconnect_adapter,
641 dop);
642 dop->download_timeout_task =
643 GNUNET_SCHEDULER_add_delayed (timeout, &download_timeout, dop);
729} 644}
730 645
731/* end of test_fs_lib.c */ 646
647/* end of fs_test_lib.c */