809fd981dd39c7e10f5b6cd6cb0b168b2c459d48
[platform/upstream/libnice.git] / tests / test-io-stream-cancelling.c
1 /*
2  * This file is part of the Nice GLib ICE library.
3  *
4  * (C) 2014 Collabora Ltd.
5  *  Contact: Philip Withnall
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is the Nice GLib ICE library.
18  *
19  * The Initial Developers of the Original Code are Collabora Ltd and Nokia
20  * Corporation. All Rights Reserved.
21  *
22  * Contributors:
23  *   Philip Withnall, Collabora Ltd.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
27  * case the provisions of LGPL are applicable instead of those above. If you
28  * wish to allow use of your version of this file only under the terms of the
29  * LGPL and not to allow others to use your version of this file under the
30  * MPL, indicate your decision by deleting the provisions above and replace
31  * them with the notice and other provisions required by the LGPL. If you do
32  * not delete the provisions above, a recipient may use your version of this
33  * file under either the MPL or the LGPL.
34  */
35 #ifdef HAVE_CONFIG_H
36 # include <config.h>
37 #endif
38
39 #include "agent.h"
40 #include "test-io-stream-common.h"
41
42 #include <stdlib.h>
43 #include <string.h>
44 #ifndef G_OS_WIN32
45 #include <unistd.h>
46 #endif
47
48 typedef struct {
49   GCancellable *cancellable;  /* owned */
50
51   GCond cond;
52   GMutex mutex;
53   gboolean blocking;  /* protected by @mutex */
54 } CancellationData;
55
56 static gpointer
57 cancellation_thread_cb (gpointer user_data)
58 {
59   CancellationData *data = user_data;
60
61   /* Wait to be signalled from read_thread_cb(). */
62   g_mutex_lock (&data->mutex);
63   while (!data->blocking)
64     g_cond_wait (&data->cond, &data->mutex);
65   g_mutex_unlock (&data->mutex);
66
67   /* Try and ensure we cancel part-way through the read, rather than before the
68    * read function is called. */
69   g_usleep (100000);
70
71   g_cancellable_cancel (data->cancellable);
72
73   return NULL;
74 }
75
76 static void
77 read_thread_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
78 {
79   CancellationData *user_data = data->user_data;
80   GError *error = NULL;
81   guint8 buf[MESSAGE_SIZE];
82   gssize len;
83
84   /* Block on receiving some data or cancellation. */
85   g_mutex_lock (&user_data->mutex);
86   user_data->blocking = TRUE;
87   g_cond_signal (&user_data->cond);
88   g_mutex_unlock (&user_data->mutex);
89
90   len = g_input_stream_read (input_stream, buf, sizeof (buf),
91       user_data->cancellable, &error);
92   g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
93   g_error_free (error);
94   g_assert_cmpint (len, ==, -1);
95
96   g_main_loop_quit (data->error_loop);
97 }
98
99 int main (void)
100 {
101   GThread *l_cancellation_thread, *r_cancellation_thread;
102   CancellationData l_data, r_data;
103
104   const TestIOStreamCallbacks callbacks = {
105     read_thread_cb,
106     NULL,
107     NULL,
108     NULL,
109   };
110
111 #ifdef G_OS_WIN32
112   WSADATA w;
113   WSAStartup (0x0202, &w);
114 #endif
115
116   l_data.cancellable = g_cancellable_new ();
117   l_data.blocking = FALSE;
118   g_cond_init (&l_data.cond);
119   g_mutex_init (&l_data.mutex);
120
121   r_data.cancellable = g_cancellable_new ();
122   r_data.blocking = FALSE;
123   g_cond_init (&r_data.cond);
124   g_mutex_init (&r_data.mutex);
125
126   l_cancellation_thread = spawn_thread ("libnice L cancel",
127       cancellation_thread_cb, &l_data);
128   r_cancellation_thread = spawn_thread ("libnice R cancel",
129       cancellation_thread_cb, &r_data);
130
131   run_io_stream_test (30, TRUE, &callbacks, &l_data, NULL, &r_data, NULL);
132
133   g_thread_join (l_cancellation_thread);
134   g_thread_join (r_cancellation_thread);
135
136   /* Free things. */
137   g_object_unref (r_data.cancellable);
138   g_object_unref (l_data.cancellable);
139   g_cond_clear (&l_data.cond);
140   g_cond_clear (&r_data.cond);
141   g_mutex_clear (&l_data.mutex);
142   g_mutex_clear (&r_data.mutex);
143
144 #ifdef G_OS_WIN32
145   WSACleanup ();
146 #endif
147
148   return 0;
149 }