Merge branch '976-disable-assert-checks' into 'master'
[glib.git] / gio / tests / socket-service.c
blob9ae76d0822347bbe75a65e2e4c4c845ebc29fc90
1 /* GLib testing framework examples and tests
3 * Copyright 2014 Red Hat, Inc.
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.1 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 Public
16 * License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
20 #include <gio/gio.h>
22 static void
23 active_notify_cb (GSocketService *service,
24 GParamSpec *pspec,
25 gpointer data)
27 gboolean *success = (gboolean *)data;
29 if (g_socket_service_is_active (service))
30 *success = TRUE;
33 static void
34 connected_cb (GObject *client,
35 GAsyncResult *result,
36 gpointer user_data)
38 GSocketService *service = G_SOCKET_SERVICE (user_data);
39 GSocketConnection *conn;
40 GError *error = NULL;
42 g_assert_true (g_socket_service_is_active (service));
44 conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
45 g_assert_no_error (error);
46 g_object_unref (conn);
48 g_socket_service_stop (service);
49 g_assert_false (g_socket_service_is_active (service));
52 static void
53 test_start_stop (void)
55 gboolean success = FALSE;
56 GInetAddress *iaddr;
57 GSocketAddress *saddr, *listening_addr;
58 GSocketService *service;
59 GError *error = NULL;
60 GSocketClient *client;
62 iaddr = g_inet_address_new_loopback (G_SOCKET_FAMILY_IPV4);
63 saddr = g_inet_socket_address_new (iaddr, 0);
64 g_object_unref (iaddr);
66 /* instanciate with g_object_new so we can pass active = false */
67 service = g_object_new (G_TYPE_SOCKET_SERVICE, "active", FALSE, NULL);
68 g_assert_false (g_socket_service_is_active (service));
70 g_signal_connect (service, "notify::active", G_CALLBACK (active_notify_cb), &success);
72 g_socket_listener_add_address (G_SOCKET_LISTENER (service),
73 saddr,
74 G_SOCKET_TYPE_STREAM,
75 G_SOCKET_PROTOCOL_TCP,
76 NULL,
77 &listening_addr,
78 &error);
79 g_assert_no_error (error);
80 g_object_unref (saddr);
82 client = g_socket_client_new ();
83 g_socket_client_connect_async (client,
84 G_SOCKET_CONNECTABLE (listening_addr),
85 NULL,
86 connected_cb, service);
87 g_object_unref (client);
88 g_object_unref (listening_addr);
90 g_socket_service_start (service);
91 g_assert_true (g_socket_service_is_active (service));
94 g_main_context_iteration (NULL, TRUE);
95 while (!success);
97 g_object_unref (service);
100 GMutex mutex_712570;
101 GCond cond_712570;
102 volatile gboolean finalized;
104 GType test_threaded_socket_service_get_type (void);
105 typedef GThreadedSocketService TestThreadedSocketService;
106 typedef GThreadedSocketServiceClass TestThreadedSocketServiceClass;
108 G_DEFINE_TYPE (TestThreadedSocketService, test_threaded_socket_service, G_TYPE_THREADED_SOCKET_SERVICE)
110 static void
111 test_threaded_socket_service_init (TestThreadedSocketService *service)
115 static void
116 test_threaded_socket_service_finalize (GObject *object)
118 G_OBJECT_CLASS (test_threaded_socket_service_parent_class)->finalize (object);
120 /* Signal the main thread that finalization completed successfully
121 * rather than hanging.
123 finalized = TRUE;
124 g_cond_signal (&cond_712570);
125 g_mutex_unlock (&mutex_712570);
128 static void
129 test_threaded_socket_service_class_init (TestThreadedSocketServiceClass *klass)
131 GObjectClass *object_class = G_OBJECT_CLASS (klass);
133 object_class->finalize = test_threaded_socket_service_finalize;
136 static gboolean
137 connection_cb (GThreadedSocketService *service,
138 GSocketConnection *connection,
139 GObject *source_object,
140 gpointer user_data)
142 /* Block until the main thread has dropped its ref to @service, so that we
143 * will drop the final ref from this thread.
145 g_mutex_lock (&mutex_712570);
147 /* The service should now have 1 ref owned by the current "run"
148 * signal emission, and another added by GThreadedSocketService for
149 * this thread. Both will be dropped after we return.
151 g_assert_cmpint (G_OBJECT (service)->ref_count, ==, 2);
153 return FALSE;
156 static void
157 client_connected_cb (GObject *client,
158 GAsyncResult *result,
159 gpointer user_data)
161 GMainLoop *loop = user_data;
162 GSocketConnection *conn;
163 GError *error = NULL;
165 conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client), result, &error);
166 g_assert_no_error (error);
168 g_object_unref (conn);
169 g_main_loop_quit (loop);
172 static void
173 test_threaded_712570 (void)
175 GSocketService *service;
176 GSocketAddress *addr, *listening_addr;
177 GMainLoop *loop;
178 GSocketClient *client;
179 GError *error = NULL;
181 g_test_bug ("712570");
183 g_mutex_lock (&mutex_712570);
185 service = g_object_new (test_threaded_socket_service_get_type (), NULL);
187 addr = g_inet_socket_address_new_from_string ("127.0.0.1", 0);
188 g_socket_listener_add_address (G_SOCKET_LISTENER (service),
189 addr,
190 G_SOCKET_TYPE_STREAM,
191 G_SOCKET_PROTOCOL_TCP,
192 NULL,
193 &listening_addr,
194 &error);
195 g_assert_no_error (error);
196 g_object_unref (addr);
198 g_signal_connect (service, "run", G_CALLBACK (connection_cb), NULL);
200 loop = g_main_loop_new (NULL, FALSE);
202 client = g_socket_client_new ();
203 g_socket_client_connect_async (client,
204 G_SOCKET_CONNECTABLE (listening_addr),
205 NULL,
206 client_connected_cb, loop);
207 g_object_unref (client);
208 g_object_unref (listening_addr);
210 g_main_loop_run (loop);
211 g_main_loop_unref (loop);
213 /* Stop the service and then wait for it to asynchronously cancel
214 * its outstanding accept() call (and drop the associated ref).
215 * At least one main context iteration is required in some circumstances
216 * to ensure that the cancellation actually happens.
218 g_socket_service_stop (G_SOCKET_SERVICE (service));
219 g_assert_false (g_socket_service_is_active (G_SOCKET_SERVICE (service)));
222 g_main_context_iteration (NULL, TRUE);
223 while (G_OBJECT (service)->ref_count > 3);
225 /* Drop our ref, then unlock the mutex and wait for the service to be
226 * finalized. (Without the fix for 712570 it would hang forever here.)
228 g_object_unref (service);
230 while (!finalized)
231 g_cond_wait (&cond_712570, &mutex_712570);
232 g_mutex_unlock (&mutex_712570);
236 main (int argc,
237 char *argv[])
239 g_test_init (&argc, &argv, NULL);
241 g_test_bug_base ("http://bugzilla.gnome.org/");
243 g_test_add_func ("/socket-service/start-stop", test_start_stop);
244 g_test_add_func ("/socket-service/threaded/712570", test_threaded_712570);
246 return g_test_run();