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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Stef Walter <stefw@collabora.co.uk>
27 /* How long to wait in ms for each iteration */
28 #define WAIT_ITERATION (10)
30 static gint num_async_operations = 0;
34 guint iterations_requested;
35 guint iterations_done;
39 mock_operation_free (gpointer user_data)
41 MockOperationData *data = user_data;
46 mock_operation_thread (GTask *task,
47 gpointer source_object,
49 GCancellable *cancellable)
51 MockOperationData *data = task_data;
54 for (i = 0; i < data->iterations_requested; i++)
56 if (g_cancellable_is_cancelled (cancellable))
58 if (g_test_verbose ())
59 g_printerr ("THRD: %u iteration %u\n", data->iterations_requested, i);
60 g_usleep (WAIT_ITERATION * 1000);
63 if (g_test_verbose ())
64 g_printerr ("THRD: %u stopped at %u\n", data->iterations_requested, i);
65 data->iterations_done = i;
67 g_task_return_boolean (task, TRUE);
71 mock_operation_timeout (gpointer user_data)
74 MockOperationData *data;
75 gboolean done = FALSE;
77 task = G_TASK (user_data);
78 data = g_task_get_task_data (task);
80 if (data->iterations_done >= data->iterations_requested)
83 if (g_cancellable_is_cancelled (g_task_get_cancellable (task)))
88 if (g_test_verbose ())
89 g_printerr ("LOOP: %u stopped at %u\n", data->iterations_requested,\
90 data->iterations_done);
91 g_task_return_boolean (task, TRUE);
92 return FALSE; /* don't call timeout again */
96 data->iterations_done++;
97 if (g_test_verbose ())
98 g_printerr ("LOOP: %u iteration %u\n", data->iterations_requested,
99 data->iterations_done);
100 return TRUE; /* call timeout */
105 mock_operation_async (guint wait_iterations,
106 gboolean run_in_thread,
107 GCancellable *cancellable,
108 GAsyncReadyCallback callback,
112 MockOperationData *data;
114 task = g_task_new (NULL, cancellable, callback, user_data);
115 data = g_new0 (MockOperationData, 1);
116 data->iterations_requested = wait_iterations;
117 g_task_set_task_data (task, data, mock_operation_free);
121 g_task_run_in_thread (task, mock_operation_thread);
122 if (g_test_verbose ())
123 g_printerr ("THRD: %d started\n", wait_iterations);
127 g_timeout_add_full (G_PRIORITY_DEFAULT, WAIT_ITERATION, mock_operation_timeout,
128 g_object_ref (task), g_object_unref);
129 if (g_test_verbose ())
130 g_printerr ("LOOP: %d started\n", wait_iterations);
133 g_object_unref (task);
137 mock_operation_finish (GAsyncResult *result,
140 MockOperationData *data;
143 g_assert (g_task_is_valid (result, NULL));
145 /* This test expects the return value to be iterations_done even
146 * when an error is set.
148 task = G_TASK (result);
149 data = g_task_get_task_data (task);
151 g_task_propagate_boolean (task, error);
152 return data->iterations_done;
158 on_mock_operation_ready (GObject *source,
159 GAsyncResult *result,
162 guint iterations_requested;
163 guint iterations_done;
164 GError *error = NULL;
166 iterations_requested = GPOINTER_TO_UINT (user_data);
167 iterations_done = mock_operation_finish (result, &error);
169 g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
170 g_error_free (error);
172 g_assert_cmpint (iterations_requested, >, iterations_done);
173 num_async_operations--;
175 if (!num_async_operations)
176 g_main_loop_quit (loop);
180 on_main_loop_timeout_quit (gpointer user_data)
182 GMainLoop *loop = user_data;
183 g_main_loop_quit (loop);
188 test_cancel_multiple_concurrent (void)
190 GCancellable *cancellable;
193 cancellable = g_cancellable_new ();
194 loop = g_main_loop_new (NULL, FALSE);
196 for (i = 0; i < 45; i++)
199 mock_operation_async (iterations, g_random_boolean (), cancellable,
200 on_mock_operation_ready, GUINT_TO_POINTER (iterations));
201 num_async_operations++;
204 /* Wait for two iterations, to give threads a chance to start up */
205 g_timeout_add (WAIT_ITERATION * 2, on_main_loop_timeout_quit, loop);
206 g_main_loop_run (loop);
207 g_assert_cmpint (num_async_operations, ==, 45);
208 if (g_test_verbose ())
209 g_printerr ("CANCEL: %d operations\n", num_async_operations);
210 g_cancellable_cancel (cancellable);
211 g_assert (g_cancellable_is_cancelled (cancellable));
213 /* Wait for all operations to be cancelled */
214 g_main_loop_run (loop);
215 g_assert_cmpint (num_async_operations, ==, 0);
217 g_object_unref (cancellable);
218 g_main_loop_unref (loop);
222 main (int argc, char *argv[])
224 g_test_init (&argc, &argv, NULL);
226 g_test_add_func ("/cancellable/multiple-concurrent", test_cancel_multiple_concurrent);
228 return g_test_run ();