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/>.
23 active_notify_cb (GSocketService
*service
,
27 gboolean
*success
= (gboolean
*)data
;
29 if (g_socket_service_is_active (service
))
34 connected_cb (GObject
*client
,
38 GSocketService
*service
= G_SOCKET_SERVICE (user_data
);
39 GSocketConnection
*conn
;
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
));
53 test_start_stop (void)
55 gboolean success
= FALSE
;
57 GSocketAddress
*saddr
, *listening_addr
;
58 GSocketService
*service
;
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
),
75 G_SOCKET_PROTOCOL_TCP
,
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
),
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
);
97 g_object_unref (service
);
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
)
111 test_threaded_socket_service_init (TestThreadedSocketService
*service
)
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.
124 g_cond_signal (&cond_712570
);
125 g_mutex_unlock (&mutex_712570
);
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
;
137 connection_cb (GThreadedSocketService
*service
,
138 GSocketConnection
*connection
,
139 GObject
*source_object
,
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);
157 client_connected_cb (GObject
*client
,
158 GAsyncResult
*result
,
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
);
173 test_threaded_712570 (void)
175 GSocketService
*service
;
176 GSocketAddress
*addr
, *listening_addr
;
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
),
190 G_SOCKET_TYPE_STREAM
,
191 G_SOCKET_PROTOCOL_TCP
,
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
),
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
);
231 g_cond_wait (&cond_712570
, &mutex_712570
);
232 g_mutex_unlock (&mutex_712570
);
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
);