1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* test-async-cancel.c - Test program for the GNOME Virtual File System.
5 Copyright (C) 1999 Free Software Foundation
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Author: Darin Adler <darin@eazel.com>
28 #include <glib/glist.h>
29 #include <glib/gmain.h>
30 #include <glib/gmessages.h>
31 #include <glib/gstrfuncs.h>
32 #include <libgnomevfs/gnome-vfs-async-ops.h>
33 #include <libgnomevfs/gnome-vfs-init.h>
34 #include <libgnomevfs/gnome-vfs-job.h>
40 #define TEST_ASSERT(expression, message) \
41 G_STMT_START { if (!(expression)) test_failed message; } G_STMT_END
43 static GnomeVFSAsyncHandle *test_handle;
44 static gpointer test_callback_data;
45 static gboolean test_done;
47 #define MAX_THREAD_WAIT 500
48 #define MAX_FD_CHECK 128
51 stop_after_log (const char *domain, GLogLevelFlags level,
52 const char *message, gpointer data)
54 void (* saved_handler)(int);
56 g_log_default_handler(domain, level, message, data);
58 saved_handler = signal (SIGINT, SIG_IGN);
60 signal(SIGINT, saved_handler);
64 make_asserts_break (const char *domain)
66 g_log_set_handler (domain,
67 (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING),
68 stop_after_log, NULL);
72 get_free_file_descriptor_count (void)
79 for (count = 0; fd < MAX_FD_CHECK; count++) {
80 fd = open ("/dev/null", O_RDONLY);
84 list = g_list_prepend (list, GINT_TO_POINTER (fd));
87 for (p = list; p != NULL; p = p->next) {
88 close (GPOINTER_TO_INT (p->data));
95 static int free_at_start;
98 get_used_file_descriptor_count (void)
100 return free_at_start - get_free_file_descriptor_count ();
104 wait_for_boolean (gboolean *wait_for_it)
112 for (i = 0; i < MAX_THREAD_WAIT; i++) {
114 g_main_context_iteration (NULL, FALSE);
123 wait_until_vfs_jobs_gone (void)
127 if (gnome_vfs_job_get_count () == 0) {
131 for (i = 0; i < MAX_THREAD_WAIT; i++) {
133 g_main_context_iteration (NULL, FALSE);
134 if (gnome_vfs_job_get_count () == 0) {
143 wait_until_vfs_jobs_gone_no_main (void)
147 if (gnome_vfs_job_get_count () == 0) {
151 for (i = 0; i < MAX_THREAD_WAIT; i++) {
153 if (gnome_vfs_job_get_count () == 0) {
161 wait_until_file_descriptors_gone (void)
165 if (get_used_file_descriptor_count () == 0) {
169 for (i = 0; i < MAX_THREAD_WAIT; i++) {
171 g_main_context_iteration (NULL, FALSE);
172 if (get_used_file_descriptor_count () == 0) {
179 static gboolean at_least_one_test_failed = FALSE;
182 test_failed (const char *format, ...)
187 va_start (arguments, format);
188 message = g_strdup_vprintf (format, arguments);
191 g_message ("test failed: %s", message);
192 at_least_one_test_failed = TRUE;
196 get_file_info_callback (GnomeVFSAsyncHandle *handle,
198 gpointer callback_data)
200 TEST_ASSERT (handle == test_handle, ("get_file_info, bad handle"));
201 TEST_ASSERT (g_list_length (results) == 1, ("get_file_info, bad list length"));
202 TEST_ASSERT (callback_data == test_callback_data, ("get_file_info, bad handle"));
205 g_free (callback_data);
211 first_get_file_info (void)
215 /* Start a get_file_info call. */
217 test_callback_data = g_malloc (1);
218 uri_list = g_list_prepend (NULL, gnome_vfs_uri_new ("file:///dev/null"));
219 gnome_vfs_async_get_file_info (&test_handle,
221 GNOME_VFS_FILE_INFO_DEFAULT,
223 get_file_info_callback,
225 g_list_free (uri_list);
227 /* Wait until it is done. */
228 TEST_ASSERT (wait_for_boolean (&test_done), ("first_get_file_info: callback was not called"));
229 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("first_get_file_info: job never went away"));
231 /* For some reason, this consumes file descriptors.
237 test_get_file_info (void)
241 /* Start a get_file_info call. */
243 test_callback_data = g_malloc (1);
244 uri_list = g_list_prepend (NULL, gnome_vfs_uri_new ("file:///dev/null"));
245 gnome_vfs_async_get_file_info (&test_handle,
247 GNOME_VFS_FILE_INFO_DEFAULT,
249 get_file_info_callback,
251 gnome_vfs_uri_list_free (uri_list);
253 /* Wait until it is done. */
254 TEST_ASSERT (wait_for_boolean (&test_done), ("get_file_info 1: callback was not called"));
255 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("get_file_info 1: job never went away"));
256 TEST_ASSERT (get_used_file_descriptor_count () == 0,
257 ("get_file_info 1: %d file descriptors leaked", get_used_file_descriptor_count ()));
258 free_at_start = get_free_file_descriptor_count ();
260 /* Cancel one right after starting it. */
262 test_callback_data = g_malloc (1);
263 uri_list = g_list_prepend (NULL, gnome_vfs_uri_new ("file:///dev/null"));
264 gnome_vfs_async_get_file_info (&test_handle,
266 GNOME_VFS_FILE_INFO_DEFAULT,
268 get_file_info_callback,
270 gnome_vfs_uri_list_free (uri_list);
271 gnome_vfs_async_cancel (test_handle);
272 g_free (test_callback_data);
274 /* Wait until it is done. */
275 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("get_file_info 2: job never went away"));
276 TEST_ASSERT (get_used_file_descriptor_count () == 0,
277 ("get_file_info 2: %d file descriptors leaked", get_used_file_descriptor_count ()));
278 TEST_ASSERT (test_done == FALSE, ("get_file_info 2: callback was called"));
279 free_at_start = get_free_file_descriptor_count ();
282 static gboolean file_open_flag;
285 file_open_callback (GnomeVFSAsyncHandle *handle,
286 GnomeVFSResult result,
287 gpointer callback_data)
289 TEST_ASSERT (handle == test_handle, ("open callback, bad handle"));
290 TEST_ASSERT (result == GNOME_VFS_OK, ("open callback, bad result"));
291 TEST_ASSERT (callback_data == test_callback_data, ("open callback, bad callback data"));
293 file_open_flag = TRUE;
296 static gboolean file_closed_flag;
299 file_close_callback (GnomeVFSAsyncHandle *handle,
300 GnomeVFSResult result,
301 gpointer callback_data)
303 TEST_ASSERT (handle == test_handle, ("close callback, bad handle"));
304 TEST_ASSERT (result == GNOME_VFS_OK, ("close callback, bad result"));
305 TEST_ASSERT (callback_data == test_callback_data, ("close callback, bad callback data"));
307 file_closed_flag = TRUE;
310 static gboolean file_read_flag;
314 file_read_callback (GnomeVFSAsyncHandle *handle,
315 GnomeVFSResult result,
317 GnomeVFSFileSize bytes_requested,
318 GnomeVFSFileSize bytes_read,
319 gpointer callback_data)
321 TEST_ASSERT (handle == test_handle, ("read callback, bad handle"));
322 TEST_ASSERT (result == GNOME_VFS_OK, ("read callback, bad result"));
323 TEST_ASSERT (buffer == read_buffer, ("read callback, bad buffer"));
324 TEST_ASSERT (bytes_requested == 1, ("read callback, bad bytes_requested"));
325 TEST_ASSERT (bytes_read == 1, ("read callback, bad bytes_read"));
326 TEST_ASSERT (callback_data == test_callback_data, ("read callback, bad callback data"));
328 file_read_flag = TRUE;
331 static gboolean directory_load_flag;
334 directory_load_callback (GnomeVFSAsyncHandle *handle,
335 GnomeVFSResult result,
338 gpointer callback_data)
341 GnomeVFSFileInfo *info;
343 for (element = list; element != NULL; element = element->next) {
344 info = element->data;
345 gnome_vfs_file_info_ref (info);
348 for (element = list; element != NULL; element = element->next) {
349 info = element->data;
350 gnome_vfs_file_info_unref (info);
353 directory_load_flag = TRUE;
356 static gboolean directory_load_failed_flag;
359 directory_load_failed_callback (GnomeVFSAsyncHandle *handle,
360 GnomeVFSResult result,
363 gpointer callback_data)
365 g_assert (result != GNOME_VFS_OK);
366 directory_load_failed_flag = TRUE;
370 test_open_read_close (void)
372 file_open_flag = FALSE;
373 gnome_vfs_async_open (&test_handle,
374 "file:///etc/passwd",
379 TEST_ASSERT (wait_for_boolean (&file_open_flag), ("open: callback was not called"));
381 file_read_flag = FALSE;
382 gnome_vfs_async_read (test_handle,
388 TEST_ASSERT (wait_for_boolean (&file_read_flag), ("open read close: read callback was not called"));
389 file_closed_flag = FALSE;
390 gnome_vfs_async_close (test_handle,
394 TEST_ASSERT (wait_for_boolean (&file_closed_flag), ("open read close: close callback was not called"));
396 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open read cancel close: job never went away"));
397 TEST_ASSERT (get_used_file_descriptor_count () == 0,
398 ("open read cancel close: %d file descriptors leaked", get_used_file_descriptor_count ()));
399 free_at_start = get_free_file_descriptor_count ();
403 test_open_read_cancel_close (void)
405 file_open_flag = FALSE;
406 gnome_vfs_async_open (&test_handle,
407 "file:///etc/passwd",
412 TEST_ASSERT (wait_for_boolean (&file_open_flag), ("open: callback was not called"));
414 file_read_flag = FALSE;
415 gnome_vfs_async_read (test_handle,
420 gnome_vfs_async_cancel (test_handle);
422 file_closed_flag = FALSE;
423 gnome_vfs_async_close (test_handle,
427 TEST_ASSERT (wait_for_boolean (&file_closed_flag), ("open read cancel close: callback was not called"));
428 TEST_ASSERT (!file_read_flag, ("open read cancel close: read callback was called"));
430 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open read cancel close: job never went away"));
431 TEST_ASSERT (get_used_file_descriptor_count () == 0,
432 ("open read cancel close: %d file descriptors leaked", get_used_file_descriptor_count ()));
433 free_at_start = get_free_file_descriptor_count ();
437 test_open_close (void)
439 file_open_flag = FALSE;
440 gnome_vfs_async_open (&test_handle,
441 "file:///etc/passwd",
446 TEST_ASSERT (wait_for_boolean (&file_open_flag), ("open: open callback was not called"));
448 file_closed_flag = FALSE;
449 gnome_vfs_async_close (test_handle,
454 TEST_ASSERT (wait_for_boolean (&file_closed_flag), ("open close: close callback was not called"));
456 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open close 1: job never went away"));
457 TEST_ASSERT (get_used_file_descriptor_count () == 0,
458 ("open close 1: %d file descriptors leaked", get_used_file_descriptor_count ()));
459 free_at_start = get_free_file_descriptor_count ();
463 empty_close_callback (GnomeVFSAsyncHandle *handle,
464 GnomeVFSResult result,
465 gpointer callback_data)
470 test_open_cancel (void)
472 file_open_flag = FALSE;
473 gnome_vfs_async_open (&test_handle,
474 "file:///etc/passwd",
479 gnome_vfs_async_cancel (test_handle);
481 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open cancel 1: job never went away"));
482 TEST_ASSERT (!file_open_flag, ("open cancel 1: open callback was called"));
483 TEST_ASSERT (get_used_file_descriptor_count () == 0,
484 ("open cancel 1: %d file descriptors leaked", get_used_file_descriptor_count ()));
485 free_at_start = get_free_file_descriptor_count ();
487 file_open_flag = FALSE;
488 gnome_vfs_async_open (&test_handle,
489 "file:///etc/passwd",
494 wait_until_vfs_jobs_gone_no_main ();
495 gnome_vfs_async_cancel (test_handle);
496 if (file_open_flag) { /* too quick */
497 gnome_vfs_async_close (test_handle, empty_close_callback, NULL);
499 TEST_ASSERT (wait_until_file_descriptors_gone (),
500 ("open cancel 2: %d file descriptors leaked", get_used_file_descriptor_count ()));
501 free_at_start = get_free_file_descriptor_count ();
502 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open cancel 2: later job never went away"));
503 TEST_ASSERT (!file_open_flag, ("open cancel 2: open callback was called"));
507 file_open_fail_callback (GnomeVFSAsyncHandle *handle,
508 GnomeVFSResult result,
509 gpointer callback_data)
511 TEST_ASSERT (handle == test_handle, ("open callback, bad handle"));
512 TEST_ASSERT (result == GNOME_VFS_ERROR_NOT_FOUND, ("open callback, bad result"));
513 TEST_ASSERT (callback_data == test_callback_data, ("open callback, bad callback data"));
515 file_open_flag = TRUE;
519 test_open_fail (void)
521 file_open_flag = FALSE;
522 gnome_vfs_async_open (&test_handle,
523 "file:///etc/mugwump-xxx",
526 file_open_fail_callback,
528 TEST_ASSERT (wait_for_boolean (&file_open_flag), ("open fail 1: callback was not called"));
529 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open fail 1: job never went away"));
530 TEST_ASSERT (get_used_file_descriptor_count () == 0,
531 ("open fail 1: %d file descriptors leaked", get_used_file_descriptor_count ()));
532 free_at_start = get_free_file_descriptor_count ();
538 for (; count > 0; count--) {
541 g_main_context_iteration (NULL, FALSE);
546 test_load_directory_cancel (int delay_till_cancel, int chunk_count)
548 GnomeVFSAsyncHandle *handle;
552 gnome_vfs_async_load_directory (&handle,
554 GNOME_VFS_FILE_INFO_GET_MIME_TYPE
555 | GNOME_VFS_FILE_INFO_FORCE_FAST_MIME_TYPE
556 | GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
559 directory_load_callback,
562 usleep (delay_till_cancel * 100);
564 directory_load_flag = FALSE;
565 gnome_vfs_async_cancel (handle);
566 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("load directory cancel 1: job never went away delay %d",
568 TEST_ASSERT (!directory_load_flag, ("load directory cancel 1: load callback was called"));
570 gnome_vfs_async_load_directory (&handle,
572 GNOME_VFS_FILE_INFO_GET_MIME_TYPE
573 | GNOME_VFS_FILE_INFO_FORCE_FAST_MIME_TYPE
574 | GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
577 directory_load_callback,
580 my_yield (delay_till_cancel);
582 directory_load_flag = FALSE;
583 gnome_vfs_async_cancel (handle);
584 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("load directory cancel 2: job never went away delay %d",
586 TEST_ASSERT (!directory_load_flag, ("load directory cancel 2: load callback was called"));
590 test_load_directory_fail (void)
592 GnomeVFSAsyncHandle *handle;
595 directory_load_failed_flag = FALSE;
596 gnome_vfs_async_load_directory (&handle,
597 "file:///strcprstskrzkrk",
598 GNOME_VFS_FILE_INFO_GET_MIME_TYPE
599 | GNOME_VFS_FILE_INFO_FORCE_FAST_MIME_TYPE
600 | GNOME_VFS_FILE_INFO_FOLLOW_LINKS,
603 directory_load_failed_callback,
606 TEST_ASSERT (wait_for_boolean (&directory_load_failed_flag), ("load directory 1: load callback was not called"));
607 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("load directory 1: job never went away"));
610 static gboolean find_directory_flag;
613 test_find_directory_callback (GnomeVFSAsyncHandle *handle,
615 gpointer callback_data)
619 find_directory_flag = TRUE;
621 for (element = results; element != NULL; element = element->next) {
622 GnomeVFSFindDirectoryResult *result_item = (GnomeVFSFindDirectoryResult *)element->data;
624 if (result_item->result == GNOME_VFS_OK) {
625 gnome_vfs_uri_ref (result_item->uri);
626 gnome_vfs_uri_unref (result_item->uri);
630 g_assert (callback_data == &find_directory_flag);
634 test_find_directory (int delay_till_cancel)
636 GnomeVFSAsyncHandle *handle;
637 GList *vfs_uri_as_list;
640 vfs_uri_as_list = g_list_append (NULL, gnome_vfs_uri_new ("file://~"));
641 vfs_uri_as_list = g_list_append (vfs_uri_as_list, gnome_vfs_uri_new ("file:///ace_of_spades"));
643 find_directory_flag = FALSE;
645 gnome_vfs_async_find_directory (&handle, vfs_uri_as_list,
646 GNOME_VFS_DIRECTORY_KIND_TRASH, FALSE, TRUE, 0777, 0,
647 test_find_directory_callback, &find_directory_flag);
649 TEST_ASSERT (wait_for_boolean (&find_directory_flag),
650 ("find directory cancel 1: callback was not called %d",
653 find_directory_flag = FALSE;
655 gnome_vfs_async_find_directory (&handle, vfs_uri_as_list,
656 GNOME_VFS_DIRECTORY_KIND_TRASH, FALSE, TRUE, 0777, 0,
657 test_find_directory_callback, &find_directory_flag);
659 usleep (delay_till_cancel * 100);
661 gnome_vfs_async_cancel (handle);
662 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("find directory cancel 2: job never went away"));
663 TEST_ASSERT (!find_directory_flag, ("find directory cancel 2: callback was called"));
666 gnome_vfs_async_find_directory (&handle, vfs_uri_as_list,
667 GNOME_VFS_DIRECTORY_KIND_TRASH, FALSE, TRUE, 0777, 0,
668 test_find_directory_callback, &find_directory_flag);
670 my_yield (delay_till_cancel);
672 find_directory_flag = FALSE;
673 gnome_vfs_async_cancel (handle);
674 TEST_ASSERT (wait_until_vfs_jobs_gone (), ("open cancel 3: job never went away"));
675 TEST_ASSERT (!find_directory_flag, ("find directory cancel 3: callback was called"));
677 gnome_vfs_uri_list_free (vfs_uri_as_list);
681 main (int argc, char **argv)
683 make_asserts_break("GnomeVFS");
686 /* Initialize our own stuff. */
687 free_at_start = get_free_file_descriptor_count ();
689 /* Do the basic tests of our own tools. */
690 TEST_ASSERT (get_used_file_descriptor_count () == 0, ("file descriptor count"));
691 TEST_ASSERT (gnome_vfs_job_get_count () == 0, ("VFS job count"));
693 /* Spend those first few file descriptors. */
694 first_get_file_info ();
695 free_at_start = get_free_file_descriptor_count ();
697 /* Test to see that a simple async. call works without leaking or anything. */
698 fprintf (stderr, "Testing get file info...\n");
699 test_get_file_info ();
700 test_get_file_info ();
701 fprintf (stderr, "Testing open, close...\n");
704 fprintf (stderr, "Testing read, close...\n");
705 test_open_read_close ();
706 test_open_read_close ();
707 fprintf (stderr, "Testing cancellation...\n");
711 fprintf (stderr, "Testing failed opens...\n");
714 fprintf (stderr, "Testing read, cancel, closes...\n");
715 test_open_read_cancel_close ();
716 test_open_read_cancel_close ();
718 fprintf (stderr, "Testing directory loads");
719 test_load_directory_fail ();
720 test_load_directory_cancel (0, 1);
721 test_load_directory_cancel (1, 1);
722 test_load_directory_cancel (10, 1);
723 test_load_directory_cancel (100, 1);
724 fprintf (stderr, ".");
725 test_load_directory_cancel (0, 1);
726 test_load_directory_cancel (1, 1);
727 test_load_directory_cancel (10, 1);
728 test_load_directory_cancel (100, 1);
729 fprintf (stderr, ".");
731 test_load_directory_cancel (0, 32);
732 test_load_directory_cancel (1, 32);
733 test_load_directory_cancel (10, 32);
734 test_load_directory_cancel (100, 32);
735 fprintf (stderr, ".");
736 test_load_directory_cancel (0, 32);
737 test_load_directory_cancel (1, 32);
738 test_load_directory_cancel (10, 32);
739 test_load_directory_cancel (100, 32);
741 fprintf (stderr, "\nTesting directory finds");
742 test_find_directory (0);
743 test_find_directory (0);
744 fprintf (stderr, ".");
745 test_find_directory (1);
746 test_find_directory (1);
747 fprintf (stderr, ".");
748 test_find_directory (10);
749 test_find_directory (10);
750 fprintf (stderr, ".");
751 test_find_directory (100);
752 test_find_directory (100);
754 fprintf (stderr, "\nTesting shutdown...\n");
755 gnome_vfs_shutdown ();
757 if (g_getenv ("_MEMPROF_SOCKET")) {
758 g_warning ("Waiting for memprof\n");
759 g_main_context_iteration (NULL, TRUE);
762 if (!at_least_one_test_failed) {
763 fprintf (stderr, "All tests passed successfully.\n");
766 /* Report to "make check" on whether it all worked or not. */
767 return at_least_one_test_failed ? EXIT_FAILURE : EXIT_SUCCESS;