2 This file is part of GNUnet.
3 Copyright (C) 2010, 2011, 2012 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file fs/fs_test_lib.c
23 * @brief library routines for testing FS publishing and downloading;
24 * this code is limited to flat files
25 * and no keywords (those functions can be tested with
26 * single-peer setups; this is for testing routing).
27 * @author Christian Grothoff
31 #include "fs_test_lib.h"
34 #define CONTENT_LIFETIME GNUNET_TIME_UNIT_HOURS
38 * Handle for a publishing operation started for testing FS.
40 struct TestPublishOperation
43 * Handle for the operation to connect to the peer's 'fs' service.
45 struct GNUNET_TESTBED_Operation *fs_op;
48 * Handle to the file sharing context using this daemon.
50 struct GNUNET_FS_Handle *fs;
53 * Function to call when upload is done.
55 GNUNET_FS_TEST_UriContinuation publish_cont;
58 * Closure for publish_cont.
60 void *publish_cont_cls;
63 * Task to abort publishing (timeout).
65 struct GNUNET_SCHEDULER_Task *publish_timeout_task;
68 * Seed for file generation.
70 uint32_t publish_seed;
73 * Context for current publishing operation.
75 struct GNUNET_FS_PublishContext *publish_context;
80 struct GNUNET_FS_Uri *publish_uri;
83 * Name of the temporary file used, or NULL for none.
85 char *publish_tmp_file;
93 * Anonymity level used.
98 * Verbosity level of the current operation.
100 unsigned int verbose;
103 * Are we testing indexing? (YES: index, NO: insert, SYSERR: simulate)
110 * Handle for a download operation started for testing FS.
112 struct TestDownloadOperation
115 * Handle for the operation to connect to the peer's 'fs' service.
117 struct GNUNET_TESTBED_Operation *fs_op;
120 * Handle to the file sharing context using this daemon.
122 struct GNUNET_FS_Handle *fs;
125 * Handle to the daemon via testing.
127 struct GNUNET_TESTING_Daemon *daemon;
130 * Function to call when download is done.
132 GNUNET_SCHEDULER_TaskCallback download_cont;
135 * Closure for download_cont.
137 void *download_cont_cls;
142 struct GNUNET_FS_Uri *uri;
145 * Task to abort downloading (timeout).
147 struct GNUNET_SCHEDULER_Task *download_timeout_task;
150 * Context for current download operation.
152 struct GNUNET_FS_DownloadContext *download_context;
160 * Anonymity level used.
165 * Seed for download verification.
167 uint32_t download_seed;
170 * Verbosity level of the current operation.
172 unsigned int verbose;
177 * Task scheduled to report on the completion of our publish operation.
179 * @param cls the publish operation context
180 * @param tc scheduler context (unused)
183 report_uri (void *cls)
185 struct TestPublishOperation *po = cls;
187 GNUNET_FS_publish_stop (po->publish_context);
188 GNUNET_TESTBED_operation_done (po->fs_op);
189 po->publish_cont (po->publish_cont_cls,
191 (GNUNET_YES == po->do_index)
192 ? po->publish_tmp_file
194 GNUNET_FS_uri_destroy (po->publish_uri);
195 if ((GNUNET_YES != po->do_index) &&
196 (NULL != po->publish_tmp_file))
197 (void) GNUNET_DISK_directory_remove (po->publish_tmp_file);
198 GNUNET_free_non_null (po->publish_tmp_file);
204 * Task scheduled to run when publish operation times out.
206 * @param cls the publish operation context
209 publish_timeout (void *cls)
211 struct TestPublishOperation *po = cls;
213 po->publish_timeout_task = NULL;
214 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
215 "Timeout while trying to publish data\n");
216 GNUNET_TESTBED_operation_done (po->fs_op);
217 GNUNET_FS_publish_stop (po->publish_context);
218 po->publish_cont (po->publish_cont_cls, NULL, NULL);
219 (void) GNUNET_DISK_directory_remove (po->publish_tmp_file);
220 GNUNET_free_non_null (po->publish_tmp_file);
226 * Progress callback for file-sharing events while publishing.
228 * @param cls the publish operation context
229 * @param info information about the event
232 publish_progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info)
234 struct TestPublishOperation *po = cls;
236 switch (info->status)
238 case GNUNET_FS_STATUS_PUBLISH_COMPLETED:
239 GNUNET_SCHEDULER_cancel (po->publish_timeout_task);
240 po->publish_timeout_task = NULL;
242 GNUNET_FS_uri_dup (info->value.publish.specifics.completed.chk_uri);
243 GNUNET_SCHEDULER_add_now (&report_uri,
247 case GNUNET_FS_STATUS_PUBLISH_PROGRESS:
249 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Publishing at %llu/%llu bytes\n",
250 (unsigned long long) info->value.publish.completed,
251 (unsigned long long) info->value.publish.size);
254 case GNUNET_FS_STATUS_PUBLISH_PROGRESS_DIRECTORY:
257 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
259 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Download at %llu/%llu bytes\n",
260 (unsigned long long) info->value.download.completed,
261 (unsigned long long) info->value.download.size);
272 * Generate test data for publishing test.
274 * @param cls pointer to uint32_t with publishing seed
275 * @param offset offset to generate data for
276 * @param max maximum number of bytes to generate
277 * @param buf where to write generated data
278 * @param emsg where to store error message (unused)
279 * @return number of bytes written to buf
282 file_generator (void *cls,
288 uint32_t *publish_seed = cls;
297 for (pos = 0; pos < 8; pos++)
298 cbuf[pos] = (uint8_t) (offset >> pos * 8);
299 for (pos = 8; pos < max; pos++)
301 mod = (255 - (offset / 1024 / 32));
304 cbuf[pos] = (uint8_t) ((offset * (*publish_seed)) % mod);
311 * Connect adapter for publishing operation.
313 * @param cls the 'struct TestPublishOperation'
314 * @param cfg configuration of the peer to connect to; will be available until
315 * GNUNET_TESTBED_operation_done() is called on the operation returned
316 * from GNUNET_TESTBED_service_connect()
317 * @return service handle to return in 'op_result', NULL on error
320 publish_connect_adapter (void *cls,
321 const struct GNUNET_CONFIGURATION_Handle *cfg)
323 struct TestPublishOperation *po = cls;
325 return GNUNET_FS_start (cfg,
327 &publish_progress_cb, po,
328 GNUNET_FS_FLAGS_NONE,
329 GNUNET_FS_OPTIONS_END);
334 * Adapter function called to destroy connection to file-sharing service.
336 * @param cls the 'struct GNUNET_FS_Handle'
337 * @param op_result unused (different for publish/download!)
340 fs_disconnect_adapter (void *cls,
343 struct GNUNET_FS_Handle *fs = op_result;
350 * Callback to be called when testbed has connected to the fs service
352 * @param cls the 'struct TestPublishOperation'
353 * @param op the operation that has been finished
354 * @param ca_result the 'struct GNUNET_FS_Handle ' (NULL on error)
355 * @param emsg error message in case the operation has failed; will be NULL if
356 * operation has executed successfully.
359 publish_fs_connect_complete_cb (void *cls,
360 struct GNUNET_TESTBED_Operation *op,
364 struct TestPublishOperation *po = cls;
365 struct GNUNET_FS_FileInformation *fi;
366 struct GNUNET_DISK_FileHandle *fh;
369 char buf[DBLOCK_SIZE];
371 struct GNUNET_FS_BlockOptions bo;
373 if (NULL == ca_result)
375 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
376 "Failed to connect to FS for publishing: %s\n", emsg);
377 po->publish_cont (po->publish_cont_cls,
379 GNUNET_TESTBED_operation_done (po->fs_op);
385 bo.expiration_time = GNUNET_TIME_relative_to_absolute (CONTENT_LIFETIME);
386 bo.anonymity_level = po->anonymity;
387 bo.content_priority = 42;
388 bo.replication_level = 1;
389 if (GNUNET_YES == po->do_index)
391 po->publish_tmp_file = GNUNET_DISK_mktemp ("fs-test-publish-index");
392 GNUNET_assert (po->publish_tmp_file != NULL);
393 fh = GNUNET_DISK_file_open (po->publish_tmp_file,
394 GNUNET_DISK_OPEN_WRITE
395 | GNUNET_DISK_OPEN_CREATE,
396 GNUNET_DISK_PERM_USER_READ
397 | GNUNET_DISK_PERM_USER_WRITE);
398 GNUNET_assert (NULL != fh);
400 while (off < po->size)
402 bsize = GNUNET_MIN (sizeof(buf), po->size - off);
404 GNUNET_assert (bsize == file_generator (&po->publish_seed, off, bsize,
406 GNUNET_assert (em == NULL);
407 GNUNET_assert (bsize == GNUNET_DISK_file_write (fh, buf, bsize));
410 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
411 fi = GNUNET_FS_file_information_create_from_file (po->fs, po,
412 po->publish_tmp_file,
413 NULL, NULL, po->do_index,
415 GNUNET_assert (NULL != fi);
419 fi = GNUNET_FS_file_information_create_from_reader (po->fs, po,
425 GNUNET_assert (NULL != fi);
427 po->publish_context =
428 GNUNET_FS_publish_start (po->fs, fi, NULL, NULL, NULL,
429 GNUNET_FS_PUBLISH_OPTION_NONE);
434 * Publish a file at the given peer.
436 * @param peer where to publish
437 * @param timeout if this operation cannot be completed within the
438 * given period, call the continuation with an error code
439 * @param anonymity option for publication
440 * @param do_index GNUNET_YES for index, GNUNET_NO for insertion,
441 * GNUNET_SYSERR for simulation
442 * @param size size of the file to publish
443 * @param seed seed to use for file generation
444 * @param verbose how verbose to be in reporting
445 * @param cont function to call when done
446 * @param cont_cls closure for cont
449 GNUNET_FS_TEST_publish (struct GNUNET_TESTBED_Peer *peer,
450 struct GNUNET_TIME_Relative timeout, uint32_t anonymity,
451 int do_index, uint64_t size, uint32_t seed,
452 unsigned int verbose,
453 GNUNET_FS_TEST_UriContinuation cont, void *cont_cls)
455 struct TestPublishOperation *po;
457 po = GNUNET_new (struct TestPublishOperation);
458 po->publish_cont = cont;
459 po->publish_cont_cls = cont_cls;
460 po->publish_seed = seed;
461 po->anonymity = anonymity;
463 po->verbose = verbose;
464 po->do_index = do_index;
465 po->fs_op = GNUNET_TESTBED_service_connect (po,
468 &publish_fs_connect_complete_cb,
470 &publish_connect_adapter,
471 &fs_disconnect_adapter,
473 po->publish_timeout_task =
474 GNUNET_SCHEDULER_add_delayed (timeout, &publish_timeout, po);
478 /* ************************** download ************************ */
482 * Task scheduled to run when download operation times out.
484 * @param cls the download operation context
487 download_timeout (void *cls)
489 struct TestDownloadOperation *dop = cls;
491 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
492 "Timeout while trying to download file\n");
493 dop->download_timeout_task = NULL;
494 GNUNET_FS_download_stop (dop->download_context,
496 GNUNET_SCHEDULER_add_now (dop->download_cont,
497 dop->download_cont_cls);
498 GNUNET_TESTBED_operation_done (dop->fs_op);
499 GNUNET_FS_uri_destroy (dop->uri);
505 * Task scheduled to report on the completion of our download operation.
507 * @param cls the download operation context
510 report_success (void *cls)
512 struct TestDownloadOperation *dop = cls;
514 GNUNET_FS_download_stop (dop->download_context,
516 GNUNET_SCHEDULER_add_now (dop->download_cont,
517 dop->download_cont_cls);
518 GNUNET_TESTBED_operation_done (dop->fs_op);
519 GNUNET_FS_uri_destroy (dop->uri);
525 * Progress callback for file-sharing events while downloading.
527 * @param cls the download operation context
528 * @param info information about the event
531 download_progress_cb (void *cls,
532 const struct GNUNET_FS_ProgressInfo *info)
534 struct TestDownloadOperation *dop = cls;
536 switch (info->status)
538 case GNUNET_FS_STATUS_DOWNLOAD_PROGRESS:
540 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
541 "Download at %llu/%llu bytes\n",
542 (unsigned long long) info->value.download.completed,
543 (unsigned long long) info->value.download.size);
546 case GNUNET_FS_STATUS_DOWNLOAD_COMPLETED:
547 GNUNET_SCHEDULER_cancel (dop->download_timeout_task);
548 dop->download_timeout_task = NULL;
549 GNUNET_SCHEDULER_add_now (&report_success, dop);
552 case GNUNET_FS_STATUS_DOWNLOAD_ACTIVE:
553 case GNUNET_FS_STATUS_DOWNLOAD_INACTIVE:
556 /* FIXME: monitor data correctness during download progress */
557 /* FIXME: do performance reports given sufficient verbosity */
558 /* FIXME: advance timeout task to "immediate" on error */
567 * Connect adapter for download operation.
569 * @param cls the 'struct TestDownloadOperation'
570 * @param cfg configuration of the peer to connect to; will be available until
571 * GNUNET_TESTBED_operation_done() is called on the operation returned
572 * from GNUNET_TESTBED_service_connect()
573 * @return service handle to return in 'op_result', NULL on error
576 download_connect_adapter (void *cls,
577 const struct GNUNET_CONFIGURATION_Handle *cfg)
579 struct TestPublishOperation *po = cls;
581 return GNUNET_FS_start (cfg,
583 &download_progress_cb, po,
584 GNUNET_FS_FLAGS_NONE,
585 GNUNET_FS_OPTIONS_END);
590 * Callback to be called when testbed has connected to the fs service
592 * @param cls the 'struct TestPublishOperation'
593 * @param op the operation that has been finished
594 * @param ca_result the 'struct GNUNET_FS_Handle ' (NULL on error)
595 * @param emsg error message in case the operation has failed; will be NULL if
596 * operation has executed successfully.
599 download_fs_connect_complete_cb (void *cls,
600 struct GNUNET_TESTBED_Operation *op,
604 struct TestDownloadOperation *dop = cls;
607 GNUNET_assert (NULL != dop->fs);
608 dop->download_context =
609 GNUNET_FS_download_start (dop->fs, dop->uri, NULL, NULL, NULL, 0, dop->size,
610 dop->anonymity, GNUNET_FS_DOWNLOAD_OPTION_NONE,
616 * Perform test download.
618 * @param peer which peer to download from
619 * @param timeout if this operation cannot be completed within the
620 * given period, call the continuation with an error code
621 * @param anonymity option for download
622 * @param seed used for file validation
623 * @param uri URI of file to download (CHK/LOC only)
624 * @param verbose how verbose to be in reporting
625 * @param cont function to call when done
626 * @param cont_cls closure for cont
629 GNUNET_FS_TEST_download (struct GNUNET_TESTBED_Peer *peer,
630 struct GNUNET_TIME_Relative timeout,
631 uint32_t anonymity, uint32_t seed,
632 const struct GNUNET_FS_Uri *uri, unsigned int verbose,
633 GNUNET_SCHEDULER_TaskCallback cont, void *cont_cls)
635 struct TestDownloadOperation *dop;
637 dop = GNUNET_new (struct TestDownloadOperation);
638 dop->uri = GNUNET_FS_uri_dup (uri);
639 dop->size = GNUNET_FS_uri_chk_get_file_size (uri);
640 dop->verbose = verbose;
641 dop->anonymity = anonymity;
642 dop->download_cont = cont;
643 dop->download_cont_cls = cont_cls;
644 dop->download_seed = seed;
646 dop->fs_op = GNUNET_TESTBED_service_connect (dop,
649 &download_fs_connect_complete_cb,
651 &download_connect_adapter,
652 &fs_disconnect_adapter,
654 dop->download_timeout_task =
655 GNUNET_SCHEDULER_add_delayed (timeout, &download_timeout, dop);
659 /* end of fs_test_lib.c */