1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2011 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Stef Walter <stefw@collabora.co.uk>
25 /* How long to wait in ms for each iteration */
26 #define WAIT_ITERATION (10)
28 static gint num_async_operations
= 0;
32 guint iterations_requested
;
33 guint iterations_done
;
37 mock_operation_free (gpointer user_data
)
39 MockOperationData
*data
= user_data
;
44 mock_operation_thread (GTask
*task
,
45 gpointer source_object
,
47 GCancellable
*cancellable
)
49 MockOperationData
*data
= task_data
;
52 for (i
= 0; i
< data
->iterations_requested
; i
++)
54 if (g_cancellable_is_cancelled (cancellable
))
56 if (g_test_verbose ())
57 g_printerr ("THRD: %u iteration %u\n", data
->iterations_requested
, i
);
58 g_usleep (WAIT_ITERATION
* 1000);
61 if (g_test_verbose ())
62 g_printerr ("THRD: %u stopped at %u\n", data
->iterations_requested
, i
);
63 data
->iterations_done
= i
;
65 g_task_return_boolean (task
, TRUE
);
69 mock_operation_timeout (gpointer user_data
)
72 MockOperationData
*data
;
73 gboolean done
= FALSE
;
75 task
= G_TASK (user_data
);
76 data
= g_task_get_task_data (task
);
78 if (data
->iterations_done
>= data
->iterations_requested
)
81 if (g_cancellable_is_cancelled (g_task_get_cancellable (task
)))
86 if (g_test_verbose ())
87 g_printerr ("LOOP: %u stopped at %u\n", data
->iterations_requested
,\
88 data
->iterations_done
);
89 g_task_return_boolean (task
, TRUE
);
90 return FALSE
; /* don't call timeout again */
94 data
->iterations_done
++;
95 if (g_test_verbose ())
96 g_printerr ("LOOP: %u iteration %u\n", data
->iterations_requested
,
97 data
->iterations_done
);
98 return TRUE
; /* call timeout */
103 mock_operation_async (guint wait_iterations
,
104 gboolean run_in_thread
,
105 GCancellable
*cancellable
,
106 GAsyncReadyCallback callback
,
110 MockOperationData
*data
;
112 task
= g_task_new (NULL
, cancellable
, callback
, user_data
);
113 data
= g_new0 (MockOperationData
, 1);
114 data
->iterations_requested
= wait_iterations
;
115 g_task_set_task_data (task
, data
, mock_operation_free
);
119 g_task_run_in_thread (task
, mock_operation_thread
);
120 if (g_test_verbose ())
121 g_printerr ("THRD: %d started\n", wait_iterations
);
125 g_timeout_add_full (G_PRIORITY_DEFAULT
, WAIT_ITERATION
, mock_operation_timeout
,
126 g_object_ref (task
), g_object_unref
);
127 if (g_test_verbose ())
128 g_printerr ("LOOP: %d started\n", wait_iterations
);
131 g_object_unref (task
);
135 mock_operation_finish (GAsyncResult
*result
,
138 MockOperationData
*data
;
141 g_assert (g_task_is_valid (result
, NULL
));
143 /* This test expects the return value to be iterations_done even
144 * when an error is set.
146 task
= G_TASK (result
);
147 data
= g_task_get_task_data (task
);
149 g_task_propagate_boolean (task
, error
);
150 return data
->iterations_done
;
156 on_mock_operation_ready (GObject
*source
,
157 GAsyncResult
*result
,
160 guint iterations_requested
;
161 guint iterations_done
;
162 GError
*error
= NULL
;
164 iterations_requested
= GPOINTER_TO_UINT (user_data
);
165 iterations_done
= mock_operation_finish (result
, &error
);
167 g_assert_error (error
, G_IO_ERROR
, G_IO_ERROR_CANCELLED
);
168 g_error_free (error
);
170 g_assert_cmpint (iterations_requested
, >, iterations_done
);
171 num_async_operations
--;
173 if (!num_async_operations
)
174 g_main_loop_quit (loop
);
178 on_main_loop_timeout_quit (gpointer user_data
)
180 GMainLoop
*loop
= user_data
;
181 g_main_loop_quit (loop
);
186 test_cancel_multiple_concurrent (void)
188 GCancellable
*cancellable
;
191 cancellable
= g_cancellable_new ();
192 loop
= g_main_loop_new (NULL
, FALSE
);
194 for (i
= 0; i
< 45; i
++)
197 mock_operation_async (iterations
, g_random_boolean (), cancellable
,
198 on_mock_operation_ready
, GUINT_TO_POINTER (iterations
));
199 num_async_operations
++;
202 /* Wait for two iterations, to give threads a chance to start up */
203 g_timeout_add (WAIT_ITERATION
* 2, on_main_loop_timeout_quit
, loop
);
204 g_main_loop_run (loop
);
205 g_assert_cmpint (num_async_operations
, ==, 45);
206 if (g_test_verbose ())
207 g_printerr ("CANCEL: %d operations\n", num_async_operations
);
208 g_cancellable_cancel (cancellable
);
209 g_assert (g_cancellable_is_cancelled (cancellable
));
211 /* Wait for all operations to be cancelled */
212 g_main_loop_run (loop
);
213 g_assert_cmpint (num_async_operations
, ==, 0);
215 g_object_unref (cancellable
);
216 g_main_loop_unref (loop
);
220 main (int argc
, char *argv
[])
222 g_test_init (&argc
, &argv
, NULL
);
224 g_test_add_func ("/cancellable/multiple-concurrent", test_cancel_multiple_concurrent
);
226 return g_test_run ();