1 | /* GLib testing framework examples and tests |
2 | * |
3 | * Copyright (C) 2008-2010 Red Hat, Inc. |
4 | * |
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. |
9 | * |
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. |
14 | * |
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/>. |
17 | * |
18 | * Author: David Zeuthen <davidz@redhat.com> |
19 | */ |
20 | |
21 | #include <gio/gio.h> |
22 | #include <unistd.h> |
23 | #include <string.h> |
24 | |
25 | #include "gdbus-tests.h" |
26 | |
27 | /* all tests rely on a global connection */ |
28 | static GDBusConnection *c = NULL; |
29 | |
30 | /* all tests rely on a shared mainloop */ |
31 | static GMainLoop *loop = NULL; |
32 | |
33 | /* ---------------------------------------------------------------------------------------------------- */ |
34 | /* Check that pending calls fail with G_IO_ERROR_CLOSED if the connection is closed */ |
35 | /* See https://bugzilla.gnome.org/show_bug.cgi?id=660637 */ |
36 | /* ---------------------------------------------------------------------------------------------------- */ |
37 | |
38 | static void |
39 | sleep_cb (GObject *source_object, |
40 | GAsyncResult *res, |
41 | gpointer user_data) |
42 | { |
43 | GError **error = user_data; |
44 | GVariant *result; |
45 | |
46 | result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, error); |
47 | g_assert (result == NULL); |
48 | g_main_loop_quit (loop); |
49 | } |
50 | |
51 | static gboolean |
52 | on_timeout (gpointer user_data) |
53 | { |
54 | /* tear down bus */ |
55 | session_bus_stop (); |
56 | return G_SOURCE_REMOVE; |
57 | } |
58 | |
59 | static void |
60 | test_connection_loss (void) |
61 | { |
62 | GDBusProxy *proxy; |
63 | GError *error; |
64 | |
65 | error = NULL; |
66 | proxy = g_dbus_proxy_new_sync (connection: c, |
67 | flags: G_DBUS_PROXY_FLAGS_NONE, |
68 | NULL, /* GDBusInterfaceInfo */ |
69 | name: "com.example.TestService" , /* name */ |
70 | object_path: "/com/example/TestObject" , /* object path */ |
71 | interface_name: "com.example.Frob" , /* interface */ |
72 | NULL, /* GCancellable */ |
73 | error: &error); |
74 | g_assert_no_error (error); |
75 | |
76 | error = NULL; |
77 | g_dbus_proxy_call (proxy, |
78 | method_name: "Sleep" , |
79 | parameters: g_variant_new (format_string: "(i)" , 100 * 1000 /* msec */), |
80 | flags: G_DBUS_CALL_FLAGS_NONE, |
81 | timeout_msec: 10 * 1000 /* msec */, |
82 | NULL, /* GCancellable */ |
83 | callback: sleep_cb, |
84 | user_data: &error); |
85 | |
86 | /* Make sure we don't exit when the bus goes away */ |
87 | g_dbus_connection_set_exit_on_close (connection: c, FALSE); |
88 | |
89 | /* Nuke the connection to the bus */ |
90 | g_timeout_add (interval: 100 /* ms */, function: on_timeout, NULL); |
91 | |
92 | g_main_loop_run (loop); |
93 | |
94 | /* If we didn't act on connection-loss we'd be getting G_IO_ERROR_TIMEOUT |
95 | * generated locally. So if we get G_IO_ERROR_CLOSED it means that we |
96 | * are acting correctly on connection loss. |
97 | */ |
98 | g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED); |
99 | g_assert (!g_dbus_error_is_remote_error (error)); |
100 | g_clear_error (err: &error); |
101 | |
102 | g_object_unref (object: proxy); |
103 | } |
104 | |
105 | /* ---------------------------------------------------------------------------------------------------- */ |
106 | |
107 | int |
108 | main (int argc, |
109 | char *argv[]) |
110 | { |
111 | GError *error; |
112 | gint ret; |
113 | gchar *path; |
114 | |
115 | g_test_init (argc: &argc, argv: &argv, NULL); |
116 | |
117 | /* all the tests rely on a shared main loop */ |
118 | loop = g_main_loop_new (NULL, FALSE); |
119 | |
120 | session_bus_up (); |
121 | |
122 | /* this is safe; testserver will exit once the bus goes away */ |
123 | path = g_test_build_filename (file_type: G_TEST_BUILT, first_path: "gdbus-testserver" , NULL); |
124 | g_assert (g_spawn_command_line_async (path, NULL)); |
125 | g_free (mem: path); |
126 | |
127 | /* Create the connection in the main thread */ |
128 | error = NULL; |
129 | c = g_bus_get_sync (bus_type: G_BUS_TYPE_SESSION, NULL, error: &error); |
130 | g_assert_no_error (error); |
131 | g_assert (c != NULL); |
132 | |
133 | ensure_gdbus_testserver_up (connection: c, NULL); |
134 | |
135 | g_test_add_func (testpath: "/gdbus/connection-loss" , test_func: test_connection_loss); |
136 | |
137 | ret = g_test_run(); |
138 | |
139 | g_object_unref (object: c); |
140 | |
141 | session_bus_down (); |
142 | |
143 | g_main_loop_unref (loop); |
144 | |
145 | return ret; |
146 | } |
147 | |