GCC Code Coverage Report


Directory: ./
File: tests/network/nmtst-helpers.h
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 118 132 89.4%
Functions: 12 14 85.7%
Branches: 94 188 50.0%

Line Branch Exec Source
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Copyright 2010 - 2014, 2018 Red Hat, Inc.
18 *
19 */
20
21 /* Static functions to help with testing */
22
23
24 /* nmtst_create_minimal_connection is copied from nm-test-utils.h. */
25
26 static inline NMConnection *
27 7 nmtst_create_minimal_connection (const char *id, const char *uuid, const char *type, NMSettingConnection **out_s_con)
28 {
29 NMConnection *con;
30 7 NMSetting *s_base = NULL;
31 NMSettingConnection *s_con;
32 14 gs_free char *uuid_free = NULL;
33
34
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 g_assert (id);
35
36
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (uuid)
37 g_assert (nm_utils_is_uuid (uuid));
38 else
39 7 uuid = uuid_free = nm_utils_uuid_generate ();
40
41
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (type) {
42 GType type_g;
43
44 7 type_g = nm_setting_lookup_type (type);
45
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 g_assert (type_g != G_TYPE_INVALID);
47
48 7 s_base = g_object_new (type_g, NULL);
49
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 7 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7 times.
7 g_assert (NM_IS_SETTING (s_base));
50 }
51
52 7 con = nm_simple_connection_new ();
53
54 7 s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
55
56 7 g_object_set (s_con,
57 NM_SETTING_CONNECTION_ID, id,
58 NM_SETTING_CONNECTION_UUID, uuid,
59 NM_SETTING_CONNECTION_TYPE, type,
60 NULL);
61 7 nm_connection_add_setting (con, NM_SETTING (s_con));
62
63
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (s_base)
64 7 nm_connection_add_setting (con, s_base);
65
66
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 if (out_s_con)
67 3 *out_s_con = s_con;
68 7 return con;
69 }
70
71
72 typedef struct {
73 GMainLoop *loop;
74 NMDevice *device;
75 NMClient *client;
76 NMConnection *connection;
77
78 NMActiveConnection *ac;
79 NMRemoteConnection *rc;
80
81 const gchar * const *client_props;
82 const gchar * const *device_props;
83
84 int client_remaining;
85 int device_remaining;
86 int connection_remaining;
87 int other_remaining;
88 } EventWaitInfo;
89
90
91 #define WAIT_CHECK_REMAINING() \
92 if (info->client_remaining == 0 && info->device_remaining == 0 && info->connection_remaining == 0 && info->other_remaining == 0) { \
93 g_debug ("Got expected events, quitting mainloop"); \
94 g_main_loop_quit (info->loop); \
95 } \
96 if (info->client_remaining < 0 || info->device_remaining < 0 || info->connection_remaining < 0 || info->other_remaining < 0) { \
97 g_error ("Pending events are negative: client: %d, device: %d, connection: %d, other: %d", info->client_remaining, info->device_remaining, info->connection_remaining, info->other_remaining); \
98 g_assert_not_reached (); \
99 }
100
101 #define WAIT_DECL() \
102 EventWaitInfo info = {0}; \
103 gint _timeout_id;
104 #define WAIT_DEVICE(_device, count, ...) \
105 info.device = (_device); \
106 info.device_remaining = (count); \
107 info.device_props = (const char *[]) {__VA_ARGS__, NULL}; \
108 g_signal_connect ((_device), "notify", G_CALLBACK (device_notify_cb), &info); \
109 connect_signals (&info, G_OBJECT (_device), info.device_props, G_CALLBACK (device_signal_cb));
110 #define WAIT_CLIENT(_client, count, ...) \
111 info.client = (_client); \
112 info.client_remaining = (count); \
113 info.client_props = (const char *[]) {__VA_ARGS__, NULL}; \
114 g_signal_connect ((_client), "notify", G_CALLBACK (client_notify_cb), &info); \
115 connect_signals (&info, G_OBJECT (_client), info.client_props, G_CALLBACK (client_signal_cb));
116 #define WAIT_CONNECTION(_connection, count, ...) \
117 info.connection = NM_CONNECTION (_connection); \
118 info.connection_remaining = (count); \
119 { const gchar* const *_signals = (const char *[]) {__VA_ARGS__, NULL}; \
120 connect_signals (&info, G_OBJECT (_connection), _signals, G_CALLBACK (connection_signal_cb)); }
121
122 #define WAIT_DESTROY() \
123 g_source_remove (_timeout_id); \
124 if (info.device) { \
125 g_signal_handlers_disconnect_by_func (info.device, G_CALLBACK (device_notify_cb), &info); \
126 g_signal_handlers_disconnect_by_func (info.device, G_CALLBACK (device_signal_cb), &info); \
127 } \
128 if (info.client) { \
129 g_signal_handlers_disconnect_by_func (info.client, G_CALLBACK (client_notify_cb), &info); \
130 g_signal_handlers_disconnect_by_func (info.client, G_CALLBACK (client_signal_cb), &info); \
131 } \
132 if (info.connection) { \
133 g_signal_handlers_disconnect_by_func (info.connection, G_CALLBACK (connection_signal_cb), &info); \
134 } \
135 g_main_loop_unref (info.loop);
136
137 #define WAIT_FINISHED(timeout) \
138 info.loop = g_main_loop_new (NULL, FALSE); \
139 _timeout_id = g_timeout_add_seconds ((timeout), timeout_cb, &info); \
140 g_main_loop_run (info.loop); \
141 WAIT_DESTROY()
142
143 static gboolean
144 timeout_cb (gpointer user_data)
145 {
146 EventWaitInfo *info = user_data;
147
148 if (info)
149 g_error ("Pending events are: client: %d, device: %d, connection: %d, other: %d", info->client_remaining, info->device_remaining, info->connection_remaining, info->other_remaining); \
150 g_assert_not_reached ();
151 return G_SOURCE_REMOVE;
152 }
153
154 static void
155 19 connect_signals (EventWaitInfo *info, GObject *object, const gchar* const* signals, GCallback handler)
156 {
157 const gchar * const* signal;
158 19 GObjectClass *class = G_OBJECT_GET_CLASS(object);
159
160
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 19 times.
52 for (signal = signals; *signal != NULL; signal++) {
161
2/2
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 7 times.
33 if (g_object_class_find_property (class, *signal))
162 26 continue;
163
164 7 g_debug ("Connecting signal handler for %s", *signal);
165 7 g_signal_connect_data (object, *signal, handler, info, NULL, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
166 }
167 19 }
168
169 static void
170 device_signal_cb (gpointer user_data)
171 {
172 EventWaitInfo *info = user_data;
173
174 g_debug ("Counting signal for device");
175
176 info->device_remaining--;
177 WAIT_CHECK_REMAINING()
178 }
179
180 static void
181 6 client_signal_cb (gpointer user_data)
182 {
183 6 EventWaitInfo *info = user_data;
184
185 6 g_debug ("Counting signal for client");
186
187 6 info->client_remaining--;
188
9/16
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✓ Branch 10 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 6 times.
6 WAIT_CHECK_REMAINING()
189 6 }
190
191 static void
192 1 connection_signal_cb (gpointer user_data)
193 {
194 1 EventWaitInfo *info = user_data;
195
196 1 g_debug ("Counting signal for connection");
197
198 1 info->connection_remaining--;
199
8/16
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
1 WAIT_CHECK_REMAINING()
200 1 }
201
202 static void
203 18 device_notify_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
204 {
205 18 EventWaitInfo *info = user_data;
206
207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 g_assert (device == info->device);
208
209
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 18 times.
18 if (!g_strv_contains (info->device_props, g_param_spec_get_name (pspec))) {
210 g_debug ("Ignoring notification for device property %s", g_param_spec_get_name (pspec));
211 return;
212 }
213
214 18 g_debug ("Counting notification for device property %s", g_param_spec_get_name (pspec));
215
216 18 info->device_remaining--;
217
10/16
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 18 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 18 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 18 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 18 times.
18 WAIT_CHECK_REMAINING()
218 }
219
220 static void
221 11 client_notify_cb (NMClient *client, GParamSpec *pspec, gpointer user_data)
222 {
223 11 EventWaitInfo *info = user_data;
224
225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 g_assert (client == info->client);
226
227
2/2
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 8 times.
11 if (!g_strv_contains (info->client_props, g_param_spec_get_name (pspec))) {
228 3 g_debug ("Ignoring notification for client property %s", g_param_spec_get_name (pspec));
229 3 return;
230 }
231
232 8 g_debug ("Counting notification for client property %s", g_param_spec_get_name (pspec));
233
234 8 info->client_remaining--;
235
10/16
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 8 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 8 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 8 times.
8 WAIT_CHECK_REMAINING()
236 }
237
238 static void
239 5 nmtst_set_device_state (NMTstcServiceInfo *sinfo, NMDevice *device, NMDeviceState state, NMDeviceStateReason reason)
240 {
241 5 GError *error = NULL;
242 5 WAIT_DECL()
243
244 5 g_debug ("Setting device %s state to %d with reason %d", nm_device_get_iface (device), state, reason);
245
246 5 g_dbus_proxy_call_sync (sinfo->proxy,
247 "SetDeviceState",
248 5 g_variant_new ("(suu)", nm_object_get_path (NM_OBJECT (device)), state, reason),
249 G_DBUS_CALL_FLAGS_NO_AUTO_START,
250 3000,
251 NULL,
252 &error);
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 g_assert_no_error (error);
254
255 5 WAIT_DEVICE(device, 2, "state-reason", "state")
256
3/6
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
5 WAIT_FINISHED(5)
257 5 }
258
259 static void
260 3 nmtst_set_wired_speed (NMTstcServiceInfo *sinfo, NMDevice *device, guint32 speed)
261 {
262 3 GError *error = NULL;
263 3 WAIT_DECL()
264
265 3 g_debug ("Setting device %s speed to %d", nm_device_get_iface (device), speed);
266
267 3 g_dbus_proxy_call_sync (sinfo->proxy,
268 "SetWiredSpeed",
269 3 g_variant_new ("(su)", nm_object_get_path (NM_OBJECT (device)), speed),
270 G_DBUS_CALL_FLAGS_NO_AUTO_START,
271 3000,
272 NULL,
273 &error);
274
275
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 g_assert_no_error (error);
276
277 3 WAIT_DEVICE(device, 2, "speed", "carrier")
278
3/6
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
3 WAIT_FINISHED(5)
279 3 }
280
281
282 static void
283 5 device_removed_cb (NMClient *client,
284 NMDevice *device,
285 gpointer user_data)
286 {
287 5 EventWaitInfo *info = user_data;
288
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 g_assert (device);
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 g_assert (device == info->device);
291
292 5 info->other_remaining--;
293
8/16
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 5 times.
5 WAIT_CHECK_REMAINING()
294 5 }
295
296 static void
297 5 nmtst_remove_device (NMTstcServiceInfo *sinfo, NMClient *client, NMDevice *device)
298 {
299 5 GError *error = NULL;
300 5 WAIT_DECL()
301
302 5 g_object_ref (device);
303
304 5 g_dbus_proxy_call_sync (sinfo->proxy,
305 "RemoveDevice",
306 5 g_variant_new ("(s)", nm_object_get_path (NM_OBJECT (device))),
307 G_DBUS_CALL_FLAGS_NO_AUTO_START,
308 3000,
309 NULL,
310 &error);
311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 g_assert_no_error (error);
312
313 5 info.device = device;
314 5 info.client = client;
315 5 info.other_remaining = 1;
316 5 g_signal_connect (client, "device-removed",
317 G_CALLBACK (device_removed_cb), &info);
318
319
3/6
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 5 times.
5 WAIT_FINISHED(5)
320
321 5 g_object_unref(device);
322 5 g_signal_handlers_disconnect_by_func (client, device_removed_cb, &info);
323 5 }
324
325 static void
326 2 add_and_activate_cb (GObject *object,
327 GAsyncResult *result,
328 gpointer user_data)
329 {
330 2 NMClient *client = NM_CLIENT (object);
331 2 EventWaitInfo *info = user_data;
332 2 GError *error = NULL;
333
334 2 info->ac = nm_client_add_and_activate_connection_finish (client, result, &error);
335
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 g_assert_no_error (error);
336
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 g_assert (info->ac != NULL);
337
338 2 info->other_remaining--;
339
9/16
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 2 times.
2 WAIT_CHECK_REMAINING()
340 2 }
341
342 static NMActiveConnection*
343 2 nmtst_add_and_activate_connection (NMTstcServiceInfo *sinfo, NMClient *client, NMDevice *device, NMConnection *conn)
344 {
345 2 WAIT_DECL()
346
347 2 nm_client_add_and_activate_connection_async (client, conn, device, NULL,
348 NULL, add_and_activate_cb, &info);
349
350 2 info.other_remaining = 1;
351 2 WAIT_CLIENT(client, 1, NM_CLIENT_ACTIVE_CONNECTIONS);
352 2 WAIT_DEVICE(device, 1, NM_DEVICE_ACTIVE_CONNECTION);
353
354 2 g_object_unref (conn);
355
356
3/6
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 2 times.
2 WAIT_FINISHED(5)
357
358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 g_assert (info.ac != NULL);
359
360 2 return info.ac;
361 }
362