nmtst: add nmtst_variant_new_vardict() function
[NetworkManager.git] / shared / nm-test-utils.h
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2 /*
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2 of the License, or (at your option) any later version.
7  *
8  * This library 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 GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with this library; if not, write to the
15  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16  * Boston, MA 02110-1301 USA.
17  *
18  * Copyright 2014 Red Hat, Inc.
19  */
20
21 #ifndef __NM_TEST_UTILS_H__
22 #define __NM_TEST_UTILS_H__
23
24 /*******************************************************************************
25  * HOWTO run tests.
26  *
27  * Our tests (make check) include this header-only file nm-test-utils.h.
28  *
29  * Logging:
30  *   In tests, nm-logging redirects to glib logging. By default, glib suppresses all debug
31  *   messages unless you set G_MESSAGES_DEBUG. To enable debug logging, you can explicitly set
32  *   G_MESSAGES_DEBUG. Otherwise, nm-test will set G_MESSAGES_DEBUG=all in debug mode (see below).
33  *   For nm-logging, you can configure the log-level and domains via NMTST_DEBUG environment
34  *   variable.
35  *
36  * Assert-logging:
37  *   Some tests assert against logged messages (g_test_expect_message()).
38  *   By specifying no-expect-message in NMTST_DEBUG, you can disable assert logging
39  *   and g_test_assert_expected_messages() will not fail.
40  *
41  * NMTST_SEED_RAND environment variable:
42  *   Tests that use random numbers from nmtst_get_rand() get seeded randomly at each start.
43  *   You can specify the seed by setting NMTST_SEED_RAND. Also, tests will print the seed
44  *   to stdout, so that you know the choosen seed.
45  *
46  *
47  * NMTST_DEBUG environment variable:
48  *
49  * "debug", "no-debug": when at test is run in debug mode, it might behave differently,
50  *   depending on the test. See nmtst_is_debug().
51  *   Known differences:
52  *    - a test might leave the logging level unspecified. In this case, running in
53  *      debug mode, will turn on DEBUG logging, otherwise WARN logging only.
54  *    - if G_MESSAGES_DEBUG is unset, nm-test will set G_MESSAGES_DEBUG=all
55  *      for tests that don't do assert-logging.
56  *   Debug mode is determined as follows (highest priority first):
57  *    - command line option --debug/--no-debug
58  *    - NMTST_DEBUG=debug/no-debug
59  *    - setting NMTST_DEBUG implies debugging turned on
60  *    - g_test_verbose()
61  *
62  * "no-expect-message": for tests that would assert against log messages, disable
63  *   those asserts.
64  *
65  * "log-level=LEVEL", "log-domains=DOMAIN": reset the log level and domain for tests.
66  *    It only has an effect for nm-logging messages.
67  *    This has no effect if the test asserts against logging (unless no-expect-message),
68  *    otherwise, changing the logging would break tests.
69  *    If you set the level to DEBUG or TRACE, it also sets G_MESSAGES_DEBUG=all (unless
70  *    in assert-logging mode and unless G_MESSAGES_DEBUG is already defined).
71  *
72  * "TRACE", this is shorthand for "log-level=TRACE".
73  *
74  * "D", this is shorthand for "log-level=TRACE,no-expect-message".
75  *
76  * "sudo-cmd=PATH": when running root tests as normal user, the test will execute
77  *   itself by invoking sudo at PATH.
78  *   For example
79  *     NMTST_DEBUG="sudo-cmd=$PWD/tools/test-sudo-wrapper.sh" make -C src/platform/tests/ check
80  *
81  * "slow|quick|thorough": enable/disable long-running tests. This sets nmtst_test_quick().
82  *   Whether long-running tests are enabled is determined as follows (highest priority first):
83  *     - specifying the value in NMTST_DEBUG has highest priority
84  *     - respect g_test_quick(), if the command line contains '-mslow', '-mquick', '-mthorough'.
85  *     - use compile time default
86  *
87  * "p=PATH"|"s=PATH": passes the path to g_test_init() as "-p" and "-s", respectively.
88  *   Unfortunately, these options conflict with "--tap" which our makefile passes to the
89  *   tests, thus it's only useful outside of `make check`.
90  *
91  *******************************************************************************/
92
93 #include "nm-default.h"
94
95 #include <arpa/inet.h>
96 #include <stdio.h>
97 #include <unistd.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <errno.h>
101
102 #include "nm-utils.h"
103
104 #ifdef __NETWORKMANAGER_LOGGING_H__
105 /* We are running tests under src/. Let's include some files by default.
106  * They are useful, and affect how nm-test-utils.h itself behaves. */
107 #include "NetworkManagerUtils.h"
108 #include "nm-keyfile-internal.h"
109 #endif
110
111 /*******************************************************************************/
112
113 /* general purpose functions that have no dependency on other nmtst functions */
114
115 #define nmtst_assert_error(error, expect_error_domain, expect_error_code, expect_error_pattern) \
116         G_STMT_START { \
117                 GError *_error = (error); \
118                 GQuark _expect_error_domain = (expect_error_domain); \
119                 const char *_expect_error_pattern = (expect_error_pattern); \
120                 \
121                 if (_expect_error_domain) \
122                         g_assert_error (_error, _expect_error_domain, (expect_error_code)); \
123                 else \
124                         g_assert (_error); \
125                 g_assert (_error->message); \
126                 if (   _expect_error_pattern \
127                     && !g_pattern_match_simple (_expect_error_pattern, _error->message)) { \
128                         g_error ("%s:%d: error message does not have expected pattern '%s'. Instead it is '%s' (%s, %d)", \
129                                  __FILE__, __LINE__, \
130                                  _expect_error_pattern, _error->message, g_quark_to_string (_error->domain), _error->code); \
131                 } \
132         } G_STMT_END
133
134 #define NMTST_WAIT(max_wait_ms, wait) \
135         ({ \
136                 gboolean _not_expired = TRUE; \
137                 gint64 _nmtst_end, _nmtst_max_wait_us = (max_wait_ms) * 1000L; \
138                 \
139                 _nmtst_end = g_get_monotonic_time () + _nmtst_max_wait_us; \
140                 while (TRUE) { \
141                         { wait }; \
142                         if (g_get_monotonic_time () > _nmtst_end) { \
143                                 _not_expired = FALSE; \
144                                 break; \
145                         } \
146                 } \
147                 _not_expired; \
148         })
149
150 #define NMTST_WAIT_ASSERT(max_wait_ms, wait) \
151         G_STMT_START { \
152                 if (!(NMTST_WAIT (max_wait_ms, wait))) \
153                         g_assert_not_reached (); \
154         } G_STMT_END
155
156 inline static void
157 _nmtst_assert_success (gboolean success, GError *error, const char *file, int line)
158 {
159         if (!success || error)
160                 g_error ("(%s:%d) FAILURE success=%d, error=%s", file, line, success, error ? error->message : "(no error)");
161 }
162 #define nmtst_assert_success(success, error) _nmtst_assert_success ((success), (error), __FILE__, __LINE__)
163
164 #define nmtst_assert_no_success(success, error) \
165         G_STMT_START { \
166                 g_assert (error); \
167                 g_assert (!(success)); \
168         } G_STMT_END
169
170 /*******************************************************************************/
171
172 struct __nmtst_internal
173 {
174         GRand *rand0;
175         guint32 rand_seed;
176         GRand *rand;
177         gboolean is_debug;
178         gboolean assert_logging;
179         gboolean no_expect_message;
180         gboolean test_quick;
181         gboolean test_tap_log;
182         char *sudo_cmd;
183         char **orig_argv;
184 };
185
186 extern struct __nmtst_internal __nmtst_internal;
187
188 #define NMTST_DEFINE() \
189 struct __nmtst_internal __nmtst_internal = { 0 }; \
190 \
191 __attribute__ ((destructor)) static void \
192 _nmtst_exit (void) \
193 { \
194         __nmtst_internal.assert_logging = FALSE; \
195         g_test_assert_expected_messages (); \
196         nmtst_free (); \
197 }
198
199
200 inline static gboolean
201 nmtst_initialized (void)
202 {
203         return !!__nmtst_internal.rand0;
204 }
205
206 #define __NMTST_LOG(cmd, ...) \
207         G_STMT_START { \
208                 g_assert (nmtst_initialized ()); \
209                 if (!__nmtst_internal.assert_logging || __nmtst_internal.no_expect_message) { \
210                         cmd (__VA_ARGS__); \
211                 } else { \
212                         printf (_NM_UTILS_MACRO_FIRST (__VA_ARGS__) "\n" _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
213                 } \
214         } G_STMT_END
215
216 /* split the string inplace at specific delimiters, allowing escaping with '\\'.
217  * Returns a zero terminated array of pointers into @str.
218  *
219  * The caller must g_free() the returned argv array.
220  **/
221 inline static char **
222 nmtst_str_split (char *str, const char *delimiters)
223 {
224         const char *d;
225         GArray *result = g_array_sized_new (TRUE, FALSE, sizeof (char *), 3);
226
227         g_assert (str);
228         g_assert (delimiters && !strchr (delimiters, '\\'));
229
230         while (*str) {
231                 gsize i = 0, j = 0;
232
233                 while (TRUE) {
234                         char c = str[i];
235
236                         if (c == '\0') {
237                                 str[j++] = 0;
238                                 break;
239                         } else if (c == '\\') {
240                                 str[j++] = str[++i];
241                                 if (!str[i])
242                                         break;
243                         } else {
244                                 for (d = delimiters; *d; d++) {
245                                         if (c == *d) {
246                                                 str[j++] = 0;
247                                                 i++;
248                                                 goto BREAK_INNER_LOOPS;
249                                         }
250                                 }
251                                 str[j++] = c;
252                         }
253                         i++;
254                 }
255
256 BREAK_INNER_LOOPS:
257                 g_array_append_val (result, str);
258                 str = &str[i];
259         }
260
261         return (char **) g_array_free (result, FALSE);
262 }
263
264
265 /* free instances allocated by nmtst (especially nmtst_init()) on shutdown
266  * to release memory. After nmtst_free(), the test is uninitialized again. */
267 inline static void
268 nmtst_free (void)
269 {
270         if (!nmtst_initialized ())
271                 return;
272
273         g_rand_free (__nmtst_internal.rand0);
274         if (__nmtst_internal.rand)
275                 g_rand_free (__nmtst_internal.rand);
276         g_free (__nmtst_internal.sudo_cmd);
277         g_strfreev (__nmtst_internal.orig_argv);
278
279         memset (&__nmtst_internal, 0, sizeof (__nmtst_internal));
280 }
281
282 inline static void
283 __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_level, const char *log_domains, gboolean *out_set_logging)
284 {
285         const char *nmtst_debug;
286         gboolean is_debug = FALSE;
287         char *c_log_level = NULL, *c_log_domains = NULL;
288         char *sudo_cmd = NULL;
289         GArray *debug_messages = g_array_new (TRUE, FALSE, sizeof (char *));
290         int i;
291         gboolean no_expect_message = FALSE;
292         gboolean _out_set_logging;
293         gboolean test_quick = FALSE;
294         gboolean test_quick_set = FALSE;
295         gboolean test_quick_argv = FALSE;
296         gs_unref_ptrarray GPtrArray *p_tests = NULL;
297         gs_unref_ptrarray GPtrArray *s_tests = NULL;
298
299         if (!out_set_logging)
300                 out_set_logging = &_out_set_logging;
301         *out_set_logging = FALSE;
302
303         g_assert (!nmtst_initialized ());
304
305         g_assert (!((!!argc) ^ (!!argv)));
306         g_assert (!argc || (g_strv_length (*argv) == *argc));
307         g_assert (!assert_logging || (!log_level && !log_domains));
308
309 #ifdef __NETWORKMANAGER_UTILS_H__
310         if (!nm_utils_get_testing_initialized ())
311                 _nm_utils_set_testing (_NM_UTILS_TEST_GENERAL);
312 #endif
313
314         if (argc)
315                 __nmtst_internal.orig_argv = g_strdupv (*argv);
316
317         __nmtst_internal.assert_logging = !!assert_logging;
318
319         nm_g_type_init ();
320
321         is_debug = g_test_verbose ();
322
323         nmtst_debug = g_getenv ("NMTST_DEBUG");
324         if (nmtst_debug) {
325                 char **d_argv, **i_argv, *nmtst_debug_copy;
326
327                 /* By setting then NMTST_DEBUG variable, @is_debug is set automatically.
328                  * This can be reverted with no-debug (on command line or environment variable). */
329                 is_debug = TRUE;
330
331                 nmtst_debug_copy = g_strdup (nmtst_debug);
332                 d_argv = nmtst_str_split (nmtst_debug_copy, ",; \t\r\n");
333
334                 for (i_argv = d_argv; *i_argv; i_argv++) {
335                         const char *debug = *i_argv;
336
337                         if (!g_ascii_strcasecmp (debug, "debug"))
338                                 is_debug = TRUE;
339                         else if (!g_ascii_strcasecmp (debug, "no-debug")) {
340                                 /* when specifying the NMTST_DEBUG variable, we set is_debug to true. Use this flag to disable this
341                                  * (e.g. for only setting the log-level, but not is_debug). */
342                                 is_debug = FALSE;
343                         } else if (!g_ascii_strncasecmp (debug, "log-level=", strlen ("log-level="))) {
344                                 g_free (c_log_level);
345                                 log_level = c_log_level = g_strdup (&debug[strlen ("log-level=")]);
346                         } else if (!g_ascii_strcasecmp (debug, "D")) {
347                                 /* shorthand for "log-level=TRACE,no-expect-message" */
348                                 g_free (c_log_level);
349                                 log_level = c_log_level = g_strdup ("TRACE");
350                                 no_expect_message = TRUE;
351                         } else if (!g_ascii_strcasecmp (debug, "TRACE")) {
352                                 g_free (c_log_level);
353                                 log_level = c_log_level = g_strdup ("TRACE");
354                         } else if (!g_ascii_strncasecmp (debug, "log-domains=", strlen ("log-domains="))) {
355                                 g_free (c_log_domains);
356                                 log_domains = c_log_domains = g_strdup (&debug[strlen ("log-domains=")]);
357                         } else if (!g_ascii_strncasecmp (debug, "sudo-cmd=", strlen ("sudo-cmd="))) {
358                                 g_free (sudo_cmd);
359                                 sudo_cmd = g_strdup (&debug[strlen ("sudo-cmd=")]);
360                         } else if (!g_ascii_strcasecmp (debug, "no-expect-message")) {
361                                 no_expect_message = TRUE;
362                         } else if (!g_ascii_strncasecmp (debug, "p=", strlen ("p="))) {
363                                 if (!p_tests)
364                                         p_tests = g_ptr_array_new_with_free_func (g_free);
365                                 g_ptr_array_add (p_tests, g_strdup (&debug[strlen ("p=")]));
366                         } else if (!g_ascii_strncasecmp (debug, "s=", strlen ("s="))) {
367                                 if (!s_tests)
368                                         s_tests = g_ptr_array_new_with_free_func (g_free);
369                                 g_ptr_array_add (s_tests, g_strdup (&debug[strlen ("s=")]));
370                         } else if (!g_ascii_strcasecmp (debug, "slow") || !g_ascii_strcasecmp (debug, "thorough")) {
371                                 test_quick = FALSE;
372                                 test_quick_set = TRUE;
373                         } else if (!g_ascii_strcasecmp (debug, "quick")) {
374                                 test_quick = TRUE;
375                                 test_quick_set = TRUE;
376                         } else {
377                                 char *msg = g_strdup_printf (">>> nmtst: ignore unrecognized NMTST_DEBUG option \"%s\"", debug);
378
379                                 g_array_append_val (debug_messages, msg);
380                         }
381                 }
382
383                 g_free (d_argv);
384                 g_free (nmtst_debug_copy);
385         }
386
387         if (__nmtst_internal.orig_argv) {
388                 char **a = __nmtst_internal.orig_argv;
389
390                 for (; *a; a++) {
391                         if (!g_ascii_strcasecmp (*a, "--debug"))
392                                 is_debug = TRUE;
393                         else if (!g_ascii_strcasecmp (*a, "--no-debug"))
394                                 is_debug = FALSE;
395                         else if (   !strcmp (*a, "-m=slow")
396                                  || !strcmp (*a, "-m=thorough")
397                                  || !strcmp (*a, "-m=quick")
398                                  || (!strcmp (*a, "-m") && *(a+1)
399                                                         && (   !strcmp (*(a+1), "quick")
400                                                             || !strcmp (*(a+1), "slow")
401                                                             || !strcmp (*(a+1), "thorough"))))
402                                 test_quick_argv = TRUE;
403                         else if (strcmp (*a, "--tap") == 0)
404                                 __nmtst_internal.test_tap_log = TRUE;
405                 }
406         }
407
408         if (!argc || g_test_initialized ()) {
409                 if (p_tests || s_tests) {
410                         char *msg = g_strdup_printf (">>> nmtst: ignore -p and -s options for test which calls g_test_init() itself");
411
412                         g_array_append_val (debug_messages, msg);
413                 }
414         } else {
415                 /* g_test_init() is a variadic function, so we cannot pass it
416                  * (variadic) arguments. If you need to pass additional parameters,
417                  * call nmtst_init() with argc==NULL and call g_test_init() yourself. */
418
419                 /* g_test_init() sets g_log_set_always_fatal() for G_LOG_LEVEL_WARNING
420                  * and G_LOG_LEVEL_CRITICAL. So, beware that the test will fail if you
421                  * have any WARN or ERR log messages -- unless you g_test_expect_message(). */
422                 GPtrArray *arg_array = g_ptr_array_new ();
423                 gs_free char **arg_array_c = NULL;
424                 int arg_array_n, j;
425                 static char **s_tests_x, **p_tests_x;
426
427                 if (*argc) {
428                         for (i = 0; i < *argc; i++)
429                                 g_ptr_array_add (arg_array, (*argv)[i]);
430                 } else
431                         g_ptr_array_add (arg_array, "./test");
432
433                 if (test_quick_set && !test_quick_argv)
434                         g_ptr_array_add (arg_array, "-m=quick");
435
436                 if (!__nmtst_internal.test_tap_log) {
437                         for (i = 0; p_tests && i < p_tests->len; i++) {
438                                 g_ptr_array_add (arg_array, "-p");
439                                 g_ptr_array_add (arg_array, p_tests->pdata[i]);
440                         }
441                         for (i = 0; s_tests && i < s_tests->len; i++) {
442                                 g_ptr_array_add (arg_array, "-s");
443                                 g_ptr_array_add (arg_array, s_tests->pdata[i]);
444                         }
445                 } else if (p_tests || s_tests) {
446                         char *msg = g_strdup_printf (">>> nmtst: ignore -p and -s options for tap-tests");
447
448                         g_array_append_val (debug_messages, msg);
449                 }
450
451                 g_ptr_array_add (arg_array, NULL);
452
453                 arg_array_n = arg_array->len - 1;
454                 arg_array_c = (char **) g_ptr_array_free (arg_array, FALSE);
455
456                 g_test_init (&arg_array_n, &arg_array_c, NULL);
457
458                 if (*argc > 1) {
459                         /* collaps argc/argv by removing the arguments detected
460                          * by g_test_init(). */
461                         for (i = 1, j = 1; i < *argc; i++) {
462                                 if ((*argv)[i] == arg_array_c[j])
463                                         j++;
464                                 else
465                                         (*argv)[i] = NULL;
466                         }
467                         for (i = 1, j = 1; i < *argc; i++) {
468                                 if ((*argv)[i]) {
469                                         (*argv)[j++] = (*argv)[i];
470                                         if (i >= j)
471                                                 (*argv)[i] = NULL;
472                                 }
473                         }
474                         *argc = j;
475                 }
476
477                 /* we must "leak" the test paths because they are not cloned by g_test_init(). */
478                 if (!__nmtst_internal.test_tap_log) {
479                         if (p_tests) {
480                                 p_tests_x = (char **) g_ptr_array_free (p_tests, FALSE);
481                                 p_tests = NULL;
482                         }
483                         if (s_tests) {
484                                 s_tests_x = (char **) g_ptr_array_free (s_tests, FALSE);
485                                 s_tests = NULL;
486                         }
487                 }
488         }
489
490         if (test_quick_set)
491                 __nmtst_internal.test_quick = test_quick;
492         else if (test_quick_argv)
493                 __nmtst_internal.test_quick = g_test_quick ();
494         else {
495 #ifdef NMTST_TEST_QUICK
496                 __nmtst_internal.test_quick = NMTST_TEST_QUICK;
497 #else
498                 __nmtst_internal.test_quick = FALSE;
499 #endif
500         }
501
502         __nmtst_internal.is_debug = is_debug;
503         __nmtst_internal.rand0 = g_rand_new_with_seed (0);
504         __nmtst_internal.sudo_cmd = sudo_cmd;
505         __nmtst_internal.no_expect_message = no_expect_message;
506
507         if (!log_level && log_domains) {
508                 /* if the log level is not specified (but the domain is), we assume
509                  * the caller wants to set it depending on is_debug */
510                 log_level = is_debug ? "DEBUG" : "WARN";
511         }
512
513         if (!__nmtst_internal.assert_logging) {
514                 gboolean success = TRUE;
515 #ifdef __NETWORKMANAGER_LOGGING_H__
516                 success = nm_logging_setup (log_level, log_domains, NULL, NULL);
517                 *out_set_logging = TRUE;
518 #endif
519                 g_assert (success);
520 #if GLIB_CHECK_VERSION(2,34,0)
521                 if (__nmtst_internal.no_expect_message)
522                         g_log_set_always_fatal (G_LOG_FATAL_MASK);
523 #else
524                 /* g_test_expect_message() is a NOP, so allow any messages */
525                 g_log_set_always_fatal (G_LOG_FATAL_MASK);
526 #endif
527         } else if (__nmtst_internal.no_expect_message) {
528                 /* We have a test that would be assert_logging, but the user specified no_expect_message.
529                  * This transforms g_test_expect_message() into a NOP, but we also have to relax
530                  * g_log_set_always_fatal(), which was set by g_test_init(). */
531                 g_log_set_always_fatal (G_LOG_FATAL_MASK);
532 #ifdef __NETWORKMANAGER_LOGGING_H__
533                 if (c_log_domains || c_log_level) {
534                         /* Normally, tests with assert_logging do not overwrite the logging level/domains because
535                          * the logging statements are part of the assertions. But if the test is run with
536                          * no-expect-message *and* the logging is set explicitly via environment variables,
537                          * we still reset the logging. */
538                         gboolean success;
539
540                         success = nm_logging_setup (log_level, log_domains, NULL, NULL);
541                         *out_set_logging = TRUE;
542                         g_assert (success);
543                 }
544 #endif
545         } else {
546 #if GLIB_CHECK_VERSION(2,34,0)
547                 /* We were called not to set logging levels. This means, that the user
548                  * expects to assert against (all) messages. Any uncought message is fatal. */
549                 g_log_set_always_fatal (G_LOG_LEVEL_MASK);
550 #else
551                 /* g_test_expect_message() is a NOP, so allow any messages */
552                 g_log_set_always_fatal (G_LOG_FATAL_MASK);
553 #endif
554         }
555
556         if ((!__nmtst_internal.assert_logging || (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message)) &&
557             (is_debug || (c_log_level && (!g_ascii_strcasecmp (c_log_level, "DEBUG") || !g_ascii_strcasecmp (c_log_level, "TRACE")))) &&
558             !g_getenv ("G_MESSAGES_DEBUG"))
559         {
560                 /* if we are @is_debug or @log_level=="DEBUG" and
561                  * G_MESSAGES_DEBUG is unset, we set G_MESSAGES_DEBUG=all.
562                  * To disable this default behaviour, set G_MESSAGES_DEBUG='' */
563
564                 /* Note that g_setenv is not thread safe, but you should anyway call
565                  * nmtst_init() at the very start. */
566                 g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
567         }
568
569         /* Delay messages until we setup logging. */
570         for (i = 0; i < debug_messages->len; i++)
571                 __NMTST_LOG (g_message, "%s", g_array_index (debug_messages, const char *, i));
572
573         g_strfreev ((char **) g_array_free (debug_messages, FALSE));
574         g_free (c_log_level);
575         g_free (c_log_domains);
576
577 #ifdef __NETWORKMANAGER_UTILS_H__
578         /* ensure that monotonic timestamp is called (because it initially logs a line) */
579         nm_utils_get_monotonic_timestamp_s ();
580 #endif
581
582 #ifdef NM_UTILS_H
583         {
584                 gs_free_error GError *error = NULL;
585
586                 if (!nm_utils_init (&error))
587                         g_assert_not_reached ();
588                 g_assert_no_error (error);
589         }
590 #endif
591 }
592
593 #ifdef __NETWORKMANAGER_LOGGING_H__
594 inline static void
595 nmtst_init_with_logging (int *argc, char ***argv, const char *log_level, const char *log_domains)
596 {
597         __nmtst_init (argc, argv, FALSE, log_level, log_domains, NULL);
598 }
599 inline static void
600 nmtst_init_assert_logging (int *argc, char ***argv, const char *log_level, const char *log_domains)
601 {
602         gboolean set_logging;
603
604         __nmtst_init (argc, argv, TRUE, NULL, NULL, &set_logging);
605
606         if (!set_logging) {
607                 gboolean success;
608
609                 success = nm_logging_setup (log_level, log_domains, NULL, NULL);
610                 g_assert (success);
611         }
612 }
613 #else
614 inline static void
615 nmtst_init (int *argc, char ***argv, gboolean assert_logging)
616 {
617         __nmtst_init (argc, argv, assert_logging, NULL, NULL, NULL);
618 }
619 #endif
620
621 inline static gboolean
622 nmtst_is_debug (void)
623 {
624         g_assert (nmtst_initialized ());
625         return __nmtst_internal.is_debug;
626 }
627
628 inline static gboolean
629 nmtst_test_quick (void)
630 {
631         g_assert (nmtst_initialized ());
632         return __nmtst_internal.test_quick;
633 }
634
635 #if GLIB_CHECK_VERSION(2,34,0)
636 #undef g_test_expect_message
637 #define g_test_expect_message(...) \
638         G_STMT_START { \
639                 g_assert (nmtst_initialized ()); \
640                 if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) { \
641                         g_debug ("nmtst: assert-logging: g_test_expect_message %s", G_STRINGIFY ((__VA_ARGS__))); \
642                 } else { \
643                         G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
644                         g_test_expect_message (__VA_ARGS__); \
645                         G_GNUC_END_IGNORE_DEPRECATIONS \
646                 } \
647         } G_STMT_END
648 #undef g_test_assert_expected_messages_internal
649 #define g_test_assert_expected_messages_internal(domain, file, line, func) \
650         G_STMT_START { \
651                 const char *_domain = (domain); \
652                 const char *_file = (file); \
653                 const char *_func = (func); \
654                 int _line = (line); \
655                 \
656                 if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) \
657                         g_debug ("nmtst: assert-logging: g_test_assert_expected_messages(%s, %s:%d, %s)", _domain?:"", _file?:"", _line, _func?:""); \
658                 \
659                 G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
660                 g_test_assert_expected_messages_internal (_domain, _file, _line, _func); \
661                 G_GNUC_END_IGNORE_DEPRECATIONS \
662         } G_STMT_END
663 #endif
664
665 /*****************************************************************************/
666
667 typedef struct _NmtstTestData NmtstTestData;
668
669 typedef void (*NmtstTestDataRelease) (const NmtstTestData *test_data);
670
671 struct _NmtstTestData {
672         const char *testpath;
673         NmtstTestDataRelease fcn_release;
674         gsize n_args;
675         gpointer args[1];
676 };
677
678 inline static void
679 _nmtst_test_data_unpack (const NmtstTestData *test_data, gsize n_args, ...)
680 {
681         gsize i;
682         va_list ap;
683         gpointer *p;
684
685         g_assert (test_data);
686         g_assert_cmpint (n_args, ==, test_data->n_args);
687
688         va_start (ap, n_args);
689         for (i = 0; i < n_args; i++) {
690                 p = va_arg (ap, gpointer *);
691
692                 g_assert (p);
693                 *p = test_data->args[i];
694         }
695         va_end (ap);
696 }
697 #define nmtst_test_data_unpack(test_data, ...) _nmtst_test_data_unpack(test_data, NM_NARG (__VA_ARGS__), ##__VA_ARGS__)
698
699 inline static void
700 _nmtst_test_data_free (gpointer data)
701 {
702         NmtstTestData *test_data = data;
703
704         g_assert (test_data);
705
706         if (test_data->fcn_release)
707                 test_data->fcn_release (test_data);
708
709         g_free ((gpointer) test_data->testpath);
710         g_free (test_data);
711 }
712
713 inline static void
714 _nmtst_add_test_func_full (const char *testpath, GTestDataFunc test_func, NmtstTestDataRelease fcn_release, gsize n_args, ...)
715 {
716         gsize i;
717         NmtstTestData *data;
718         va_list ap;
719
720         data = g_malloc (G_STRUCT_OFFSET (NmtstTestData, args) + sizeof (gpointer) * (n_args + 1));
721
722         data->testpath = g_strdup (testpath);
723         data->fcn_release = fcn_release;
724         data->n_args = n_args;
725         va_start (ap, n_args);
726         for (i = 0; i < n_args; i++)
727                 data->args[i] = va_arg (ap, gpointer);
728         data->args[i] = NULL;
729         va_end (ap);
730
731         g_test_add_data_func_full (testpath,
732                                    data,
733                                    test_func,
734                                    _nmtst_test_data_free);
735 }
736 #define nmtst_add_test_func_full(testpath, test_func, fcn_release, ...) _nmtst_add_test_func_full(testpath, test_func, fcn_release, NM_NARG (__VA_ARGS__), ##__VA_ARGS__)
737 #define nmtst_add_test_func(testpath, test_func, ...) nmtst_add_test_func_full(testpath, test_func, NULL, ##__VA_ARGS__)
738
739 /*****************************************************************************/
740
741 inline static GRand *
742 nmtst_get_rand0 (void)
743 {
744         g_assert (nmtst_initialized ());
745         return __nmtst_internal.rand0;
746 }
747
748 inline static GRand *
749 nmtst_get_rand (void)
750 {
751         g_assert (nmtst_initialized ());
752
753         if (G_UNLIKELY (!__nmtst_internal.rand)) {
754                 guint32 seed;
755                 const char *str;
756
757                 if ((str = g_getenv ("NMTST_SEED_RAND"))) {
758                         gchar *s;
759                         gint64 i;
760
761                         i = g_ascii_strtoll (str, &s, 0);
762                         g_assert (s[0] == '\0' && i >= 0 && i < G_MAXUINT32);
763
764                         seed = i;
765                         __nmtst_internal.rand = g_rand_new_with_seed (seed);
766                 } else {
767                         __nmtst_internal.rand = g_rand_new ();
768
769                         seed = g_rand_int (__nmtst_internal.rand);
770                         g_rand_set_seed (__nmtst_internal.rand, seed);
771                 }
772                 __nmtst_internal.rand_seed = seed;
773
774                 g_print ("\nnmtst: initialize nmtst_get_rand() with NMTST_SEED_RAND=%u\n", seed);
775         }
776         return __nmtst_internal.rand;
777 }
778
779 inline static guint32
780 nmtst_get_rand_int (void)
781 {
782         return g_rand_int (nmtst_get_rand ());
783 }
784
785 inline static void *
786 nmtst_rand_perm (GRand *rand, void *dst, const void *src, gsize elmt_size, gsize n_elmt)
787 {
788         gsize i, j;
789         char *p_, *pj;
790         char *bu;
791
792         g_assert (dst);
793         g_assert (elmt_size > 0);
794         g_assert (n_elmt < G_MAXINT32);
795
796         if (n_elmt == 0)
797                 return dst;
798
799         if (src && dst != src)
800                 memcpy (dst, src, elmt_size * n_elmt);
801
802         if (!rand)
803                 rand = nmtst_get_rand ();
804
805         bu = g_slice_alloc (elmt_size);
806
807         p_ = dst;
808         for (i = n_elmt; i > 1; i--) {
809                 j = g_rand_int_range (rand, 0, i);
810
811                 if (j != 0) {
812                         pj = &p_[j * elmt_size];
813
814                         /* swap */
815                         memcpy (bu, p_, elmt_size);
816                         memcpy (p_, pj, elmt_size);
817                         memcpy (pj, bu, elmt_size);
818                 }
819                 p_ += elmt_size;
820         }
821
822         g_slice_free1 (elmt_size, bu);
823         return dst;
824 }
825
826 /*****************************************************************************/
827
828 inline static gboolean
829 _nmtst_main_loop_run_timeout (gpointer user_data)
830 {
831         GMainLoop **p_loop = user_data;
832
833         g_assert (p_loop);
834         g_assert (*p_loop);
835
836         g_main_loop_quit (*p_loop);
837         *p_loop = NULL;
838
839         return G_SOURCE_REMOVE;
840 }
841
842 inline static gboolean
843 nmtst_main_loop_run (GMainLoop *loop, int timeout_ms)
844 {
845         GSource *source = NULL;
846         guint id = 0;
847         GMainLoop *loopx = loop;
848
849         if (timeout_ms > 0) {
850                 source = g_timeout_source_new (timeout_ms);
851                 g_source_set_callback (source, _nmtst_main_loop_run_timeout, &loopx, NULL);
852                 id = g_source_attach (source, g_main_loop_get_context (loop));
853                 g_assert (id);
854                 g_source_unref (source);
855         }
856
857         g_main_loop_run (loop);
858
859         /* if the timeout was reached, return FALSE. */
860         return loopx != NULL;
861 }
862
863 inline static void
864 _nmtst_main_loop_quit_on_notify (GObject *object, GParamSpec *pspec, gpointer user_data)
865 {
866         GMainLoop *loop = user_data;
867
868         g_assert (G_IS_OBJECT (object));
869         g_assert (loop);
870
871         g_main_loop_quit (loop);
872 }
873 #define nmtst_main_loop_quit_on_notify ((GCallback) _nmtst_main_loop_quit_on_notify)
874
875 /*****************************************************************************/
876
877 inline static const char *
878 nmtst_get_sudo_cmd (void)
879 {
880         g_assert (nmtst_initialized ());
881         return __nmtst_internal.sudo_cmd;
882 }
883
884 inline static void
885 nmtst_reexec_sudo (void)
886 {
887         char *str;
888         char **argv;
889         int i;
890         int errsv;
891
892         g_assert (nmtst_initialized ());
893         g_assert (__nmtst_internal.orig_argv);
894
895         if (!__nmtst_internal.sudo_cmd)
896                 return;
897
898         str = g_strjoinv (" ", __nmtst_internal.orig_argv);
899         __NMTST_LOG (g_message, ">> exec %s %s", __nmtst_internal.sudo_cmd, str);
900
901         argv = g_new0 (char *, 1 + g_strv_length (__nmtst_internal.orig_argv) + 1);
902         argv[0] = __nmtst_internal.sudo_cmd;
903         for (i = 0; __nmtst_internal.orig_argv[i]; i++)
904                 argv[i+1] = __nmtst_internal.orig_argv[i];
905
906         execvp (__nmtst_internal.sudo_cmd, argv);
907
908         errsv = errno;
909         g_error (">> exec %s failed: %d - %s", __nmtst_internal.sudo_cmd, errsv, strerror (errsv));
910 }
911
912 /*****************************************************************************/
913
914 inline static gsize
915 nmtst_find_all_indexes (gpointer *elements,
916                         gsize n_elements,
917                         gpointer *needles,
918                         gsize n_needles,
919                         gboolean (*equal_fcn) (gpointer element, gpointer needle, gpointer user_data),
920                         gpointer user_data,
921                         gssize *out_idx)
922 {
923         gsize i, j, k;
924         gsize found = 0;
925
926         for (i = 0; i < n_needles; i++) {
927                 gssize idx = -1;
928
929                 for (j = 0; j < n_elements; j++) {
930
931                         /* no duplicates */
932                         for (k = 0; k < i; k++) {
933                                 if (out_idx[k] == j)
934                                         goto next;
935                         }
936
937                         if (equal_fcn (elements[j], needles[i], user_data)) {
938                                 idx = j;
939                                 break;
940                         }
941 next:
942                         ;
943                 }
944
945                 out_idx[i] = idx;
946                 if (idx >= 0)
947                         found++;
948         }
949
950         return found;
951 }
952
953 /*****************************************************************************/
954
955 #define __define_nmtst_static(NUM,SIZE) \
956 inline static const char * \
957 nmtst_static_##SIZE##_##NUM (const char *str) \
958 { \
959         gsize l; \
960         static char buf[SIZE]; \
961 \
962         if (!str) \
963                 return NULL; \
964         l = g_strlcpy (buf, str, sizeof (buf)); \
965         g_assert (l < sizeof (buf)); \
966         return buf; \
967 }
968 __define_nmtst_static(01, 1024)
969 __define_nmtst_static(02, 1024)
970 __define_nmtst_static(03, 1024)
971 #undef __define_nmtst_static
972
973 inline static const char *
974 nmtst_uuid_generate (void)
975 {
976         static char u[37];
977         gs_free char *m = NULL;
978
979         m = nm_utils_uuid_generate ();
980         g_assert (m && strlen (m) == sizeof (u) - 1);
981         memcpy (u, m, sizeof (u));
982         return u;
983 }
984
985 #define NMTST_SWAP(x,y) \
986         G_STMT_START { \
987                 char __nmtst_swap_temp[sizeof(x) == sizeof(y) ? (signed) sizeof(x) : -1]; \
988                 memcpy(__nmtst_swap_temp, &y, sizeof(x)); \
989                 memcpy(&y,                &x, sizeof(x)); \
990                 memcpy(&x, __nmtst_swap_temp, sizeof(x)); \
991         } G_STMT_END
992
993 #define nmtst_assert_str_has_substr(str, substr) \
994         G_STMT_START { \
995                 const char *__str = (str); \
996                 const char *__substr = (substr); \
997                 \
998                 g_assert (__str); \
999                 g_assert (__substr); \
1000                 if (strstr (__str, __substr) == NULL) \
1001                         g_error ("%s:%d: Expects \"%s\" but got \"%s\"", __FILE__, __LINE__, __substr, __str); \
1002         } G_STMT_END
1003
1004 inline static guint32
1005 nmtst_inet4_from_string (const char *str)
1006 {
1007         guint32 addr;
1008         int success;
1009
1010         if (!str)
1011                 return 0;
1012
1013         success = inet_pton (AF_INET, str, &addr);
1014
1015         g_assert (success == 1);
1016
1017         return addr;
1018 }
1019
1020 inline static const struct in6_addr *
1021 nmtst_inet6_from_string (const char *str)
1022 {
1023         static struct in6_addr addr;
1024         int success;
1025
1026         if (!str)
1027                 addr = in6addr_any;
1028         else {
1029                 success = inet_pton (AF_INET6, str, &addr);
1030                 g_assert (success == 1);
1031         }
1032
1033         return &addr;
1034 }
1035
1036 inline static void
1037 _nmtst_assert_ip4_address (const char *file, int line, in_addr_t addr, const char *str_expected)
1038 {
1039         if (nmtst_inet4_from_string (str_expected) != addr) {
1040                 char buf[100];
1041
1042                 g_error ("%s:%d: Unexpected IPv4 address: expected %s, got %s",
1043                          file, line, str_expected ? str_expected : "0.0.0.0",
1044                          inet_ntop (AF_INET, &addr, buf, sizeof (buf)));
1045         }
1046 }
1047 #define nmtst_assert_ip4_address(addr, str_expected) _nmtst_assert_ip4_address (__FILE__, __LINE__, addr, str_expected)
1048
1049 inline static void
1050 _nmtst_assert_ip6_address (const char *file, int line, const struct in6_addr *addr, const char *str_expected)
1051 {
1052         struct in6_addr any = in6addr_any;
1053
1054         if (!addr)
1055                 addr = &any;
1056
1057         if (memcmp (nmtst_inet6_from_string (str_expected), addr, sizeof (*addr)) != 0) {
1058                 char buf[100];
1059
1060                 g_error ("%s:%d: Unexpected IPv6 address: expected %s, got %s",
1061                          file, line, str_expected ? str_expected : "::",
1062                          inet_ntop (AF_INET6, addr, buf, sizeof (buf)));
1063         }
1064 }
1065 #define nmtst_assert_ip6_address(addr, str_expected) _nmtst_assert_ip6_address (__FILE__, __LINE__, addr, str_expected)
1066
1067 #define nmtst_spawn_sync(working_directory, standard_out, standard_err, assert_exit_status, ...) \
1068         __nmtst_spawn_sync (working_directory, standard_out, standard_err, assert_exit_status, ##__VA_ARGS__, NULL)
1069 inline static gint
1070 __nmtst_spawn_sync (const char *working_directory, char **standard_out, char **standard_err, int assert_exit_status, ...) G_GNUC_NULL_TERMINATED;
1071 inline static gint
1072 __nmtst_spawn_sync (const char *working_directory, char **standard_out, char **standard_err, int assert_exit_status, ...)
1073 {
1074         gint exit_status = 0;
1075         GError *error = NULL;
1076         char *arg;
1077         va_list va_args;
1078         GPtrArray *argv = g_ptr_array_new ();
1079         gboolean success;
1080
1081         va_start (va_args, assert_exit_status);
1082         while ((arg = va_arg (va_args, char *)))
1083                 g_ptr_array_add (argv, arg);
1084         va_end (va_args);
1085
1086         g_assert (argv->len >= 1);
1087         g_ptr_array_add (argv, NULL);
1088
1089         success = g_spawn_sync (working_directory,
1090                                 (char**) argv->pdata,
1091                                 NULL,
1092                                 0 /*G_SPAWN_DEFAULT*/,
1093                                 NULL,
1094                                 NULL,
1095                                 standard_out,
1096                                 standard_err,
1097                                 &exit_status,
1098                                 &error);
1099         if (!success)
1100                 g_error ("nmtst_spawn_sync(%s): %s", ((char **) argv->pdata)[0], error->message);
1101         g_assert (!error);
1102
1103         g_assert (!standard_out || *standard_out);
1104         g_assert (!standard_err || *standard_err);
1105
1106         if (assert_exit_status != -1) {
1107                 /* exit status is a guint8 on success. Set @assert_exit_status to -1
1108                  * not to check for the exit status. */
1109                 g_assert (WIFEXITED (exit_status));
1110                 g_assert_cmpint (WEXITSTATUS (exit_status), ==, assert_exit_status);
1111         }
1112
1113         g_ptr_array_free (argv, TRUE);
1114         return exit_status;
1115 }
1116
1117 /*******************************************************************************/
1118
1119 inline static char *
1120 nmtst_file_resolve_relative_path (const char *rel, const char *cwd)
1121 {
1122         gs_free char *cwd_free = NULL;
1123
1124         g_assert (rel && *rel);
1125
1126         if (g_path_is_absolute (rel))
1127                 return g_strdup (rel);
1128
1129         if (!cwd)
1130                 cwd = cwd_free = g_get_current_dir ();
1131         return g_build_filename (cwd, rel, NULL);
1132 }
1133
1134 inline static void
1135 _nmtst_assert_resolve_relative_path_equals (const char *f1, const char *f2, const char *file, int line)
1136 {
1137         gs_free char *p1 = NULL, *p2 = NULL;
1138
1139         p1 = nmtst_file_resolve_relative_path (f1, NULL);
1140         p2 = nmtst_file_resolve_relative_path (f2, NULL);
1141         g_assert (p1 && *p1);
1142
1143         /* Fixme: later we might need to coalesce repeated '/', "./", and "../".
1144          * For now, it's good enough. */
1145         if (g_strcmp0 (p1, p2) != 0)
1146                 g_error ("%s:%d : filenames don't match \"%s\" vs. \"%s\" // \"%s\" - \"%s\"", file, line, f1, f2, p1, p2);
1147 }
1148 #define nmtst_assert_resolve_relative_path_equals(f1, f2) _nmtst_assert_resolve_relative_path_equals (f1, f2, __FILE__, __LINE__);
1149
1150 /*******************************************************************************/
1151
1152 #ifdef __NETWORKMANAGER_PLATFORM_H__
1153
1154 inline static NMPlatformIP6Address *
1155 nmtst_platform_ip6_address (const char *address, const char *peer_address, guint plen)
1156 {
1157         static NMPlatformIP6Address addr;
1158
1159         memset (&addr, 0, sizeof (addr));
1160         addr.address = *nmtst_inet6_from_string (address);
1161         addr.peer_address = *nmtst_inet6_from_string (peer_address);
1162         addr.plen = plen;
1163
1164         return &addr;
1165 }
1166
1167 inline static NMPlatformIP6Address *
1168 nmtst_platform_ip6_address_full (const char *address, const char *peer_address, guint plen,
1169                                  int ifindex, NMIPConfigSource source, guint32 timestamp,
1170                                  guint32 lifetime, guint32 preferred, guint32 flags)
1171 {
1172         NMPlatformIP6Address *addr = nmtst_platform_ip6_address (address, peer_address, plen);
1173
1174         addr->ifindex = ifindex;
1175         addr->source = source;
1176         addr->timestamp = timestamp;
1177         addr->lifetime = lifetime;
1178         addr->preferred = preferred;
1179         addr->n_ifa_flags = flags;
1180
1181         return addr;
1182 }
1183
1184 inline static NMPlatformIP4Route *
1185 nmtst_platform_ip4_route (const char *network, guint plen, const char *gateway)
1186 {
1187         static NMPlatformIP4Route route;
1188
1189         memset (&route, 0, sizeof (route));
1190         route.network = nmtst_inet4_from_string (network);
1191         route.plen = plen;
1192         route.gateway = nmtst_inet4_from_string (gateway);
1193
1194         return &route;
1195 }
1196
1197 inline static NMPlatformIP4Route *
1198 nmtst_platform_ip4_route_full (const char *network, guint plen, const char *gateway,
1199                                int ifindex, NMIPConfigSource source,
1200                                guint metric, guint mss,
1201                                guint8 scope,
1202                                const char *pref_src)
1203 {
1204         NMPlatformIP4Route *route = nmtst_platform_ip4_route (network, plen, gateway);
1205
1206         route->ifindex = ifindex;
1207         route->source = source;
1208         route->metric = metric;
1209         route->mss = mss;
1210         route->scope_inv = nm_platform_route_scope_inv (scope);
1211         route->pref_src = nmtst_inet4_from_string (pref_src);
1212
1213         return route;
1214 }
1215
1216 inline static NMPlatformIP6Route *
1217 nmtst_platform_ip6_route (const char *network, guint plen, const char *gateway)
1218 {
1219         static NMPlatformIP6Route route;
1220
1221         memset (&route, 0, sizeof (route));
1222         route.network = *nmtst_inet6_from_string (network);
1223         route.plen = plen;
1224         route.gateway = *nmtst_inet6_from_string (gateway);
1225
1226         return &route;
1227 }
1228
1229 inline static NMPlatformIP6Route *
1230 nmtst_platform_ip6_route_full (const char *network, guint plen, const char *gateway,
1231                                int ifindex, NMIPConfigSource source,
1232                                guint metric, guint mss)
1233 {
1234         NMPlatformIP6Route *route = nmtst_platform_ip6_route (network, plen, gateway);
1235
1236         route->ifindex = ifindex;
1237         route->source = source;
1238         route->metric = metric;
1239         route->mss = mss;
1240
1241         return route;
1242 }
1243
1244 inline static int
1245 _nmtst_platform_ip4_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data)
1246 {
1247         return nm_platform_ip4_route_cmp ((const NMPlatformIP4Route *) a, (const NMPlatformIP4Route *) b);
1248 }
1249
1250 inline static void
1251 nmtst_platform_ip4_routes_equal (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gsize len, gboolean ignore_order)
1252 {
1253         gsize i;
1254         gs_free const NMPlatformIP4Route *c_a = NULL, *c_b = NULL;
1255
1256         g_assert (a);
1257         g_assert (b);
1258
1259         if (ignore_order) {
1260                 a = c_a = g_memdup (a, sizeof (NMPlatformIP4Route) * len);
1261                 b = c_b = g_memdup (b, sizeof (NMPlatformIP4Route) * len);
1262                 g_qsort_with_data (c_a, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL);
1263                 g_qsort_with_data (c_b, len, sizeof (NMPlatformIP4Route), _nmtst_platform_ip4_routes_equal_sort, NULL);
1264         }
1265
1266         for (i = 0; i < len; i++) {
1267                 if (nm_platform_ip4_route_cmp (&a[i], &b[i]) != 0) {
1268                         char buf[sizeof (_nm_utils_to_string_buffer)];
1269
1270                         g_error ("Error comparing IPv4 route[%lu]: %s vs %s", (long unsigned) i,
1271                                  nm_platform_ip4_route_to_string (&a[i], NULL, 0),
1272                                  nm_platform_ip4_route_to_string (&b[i], buf, sizeof (buf)));
1273                         g_assert_not_reached ();
1274                 }
1275         }
1276 }
1277
1278 inline static int
1279 _nmtst_platform_ip6_routes_equal_sort (gconstpointer a, gconstpointer b, gpointer user_data)
1280 {
1281         return nm_platform_ip6_route_cmp ((const NMPlatformIP6Route *) a, (const NMPlatformIP6Route *) b);
1282 }
1283
1284 inline static void
1285 nmtst_platform_ip6_routes_equal (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, gsize len, gboolean ignore_order)
1286 {
1287         gsize i;
1288         gs_free const NMPlatformIP6Route *c_a = NULL, *c_b = NULL;
1289
1290         g_assert (a);
1291         g_assert (b);
1292
1293         if (ignore_order) {
1294                 a = c_a = g_memdup (a, sizeof (NMPlatformIP6Route) * len);
1295                 b = c_b = g_memdup (b, sizeof (NMPlatformIP6Route) * len);
1296                 g_qsort_with_data (c_a, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL);
1297                 g_qsort_with_data (c_b, len, sizeof (NMPlatformIP6Route), _nmtst_platform_ip6_routes_equal_sort, NULL);
1298         }
1299
1300         for (i = 0; i < len; i++) {
1301                 if (nm_platform_ip6_route_cmp (&a[i], &b[i]) != 0) {
1302                         char buf[sizeof (_nm_utils_to_string_buffer)];
1303
1304                         g_error ("Error comparing IPv6 route[%lu]: %s vs %s", (long unsigned) i,
1305                                  nm_platform_ip6_route_to_string (&a[i], NULL, 0),
1306                                  nm_platform_ip6_route_to_string (&b[i], buf, sizeof (buf)));
1307                         g_assert_not_reached ();
1308                 }
1309         }
1310 }
1311
1312 #endif
1313
1314
1315 #ifdef __NETWORKMANAGER_IP4_CONFIG_H__
1316
1317 inline static NMIP4Config *
1318 nmtst_ip4_config_clone (NMIP4Config *config)
1319 {
1320         NMIP4Config *copy = nm_ip4_config_new (-1);
1321
1322         g_assert (copy);
1323         g_assert (config);
1324         nm_ip4_config_replace (copy, config, NULL);
1325         return copy;
1326 }
1327
1328 #endif
1329
1330
1331 #ifdef __NETWORKMANAGER_IP6_CONFIG_H__
1332
1333 inline static NMIP6Config *
1334 nmtst_ip6_config_clone (NMIP6Config *config)
1335 {
1336         NMIP6Config *copy = nm_ip6_config_new (-1);
1337
1338         g_assert (copy);
1339         g_assert (config);
1340         nm_ip6_config_replace (copy, config, NULL);
1341         return copy;
1342 }
1343
1344 #endif
1345
1346 #ifdef NM_SETTING_IP_CONFIG_H
1347 inline static void
1348 nmtst_setting_ip_config_add_address (NMSettingIPConfig *s_ip,
1349                                      const char *address,
1350                                      guint prefix)
1351 {
1352         NMIPAddress *addr;
1353         int family;
1354
1355         g_assert (s_ip);
1356
1357         if (nm_utils_ipaddr_valid (AF_INET, address))
1358                 family = AF_INET;
1359         else if (nm_utils_ipaddr_valid (AF_INET6, address))
1360                 family = AF_INET6;
1361         else
1362                 g_assert_not_reached ();
1363
1364         addr = nm_ip_address_new (family, address, prefix, NULL);
1365         g_assert (addr);
1366         g_assert (nm_setting_ip_config_add_address (s_ip, addr));
1367         nm_ip_address_unref (addr);
1368 }
1369
1370 inline static void
1371 nmtst_setting_ip_config_add_route (NMSettingIPConfig *s_ip,
1372                                    const char *dest,
1373                                    guint prefix,
1374                                    const char *next_hop,
1375                                    gint64 metric)
1376 {
1377         NMIPRoute *route;
1378         int family;
1379
1380         g_assert (s_ip);
1381
1382         if (nm_utils_ipaddr_valid (AF_INET, dest))
1383                 family = AF_INET;
1384         else if (nm_utils_ipaddr_valid (AF_INET6, dest))
1385                 family = AF_INET6;
1386         else
1387                 g_assert_not_reached ();
1388
1389         route = nm_ip_route_new (family, dest, prefix, next_hop, metric, NULL);
1390         g_assert (route);
1391         g_assert (nm_setting_ip_config_add_route (s_ip, route));
1392         nm_ip_route_unref (route);
1393 }
1394 #endif /* NM_SETTING_IP_CONFIG_H */
1395
1396 #if (defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__)) || (defined(NM_CONNECTION_H))
1397
1398 inline static NMConnection *
1399 nmtst_clone_connection (NMConnection *connection)
1400 {
1401         g_assert (NM_IS_CONNECTION (connection));
1402
1403 #if defined(__NM_SIMPLE_CONNECTION_H__)
1404         return nm_simple_connection_new_clone (connection);
1405 #else
1406         return nm_connection_duplicate (connection);
1407 #endif
1408 }
1409
1410 inline static NMConnection *
1411 nmtst_create_minimal_connection (const char *id, const char *uuid, const char *type, NMSettingConnection **out_s_con)
1412 {
1413         NMConnection *con;
1414         NMSetting *s_base = NULL;
1415         NMSettingConnection *s_con;
1416         gs_free char *uuid_free = NULL;
1417
1418         g_assert (id);
1419
1420         if (uuid)
1421                 g_assert (nm_utils_is_uuid (uuid));
1422         else
1423                 uuid = uuid_free = nm_utils_uuid_generate ();
1424
1425         if (type) {
1426                 GType type_g;
1427
1428 #if defined(__NM_SIMPLE_CONNECTION_H__)
1429                 type_g = nm_setting_lookup_type (type);
1430 #else
1431                 type_g = nm_connection_lookup_setting_type (type);
1432 #endif
1433
1434                 g_assert (type_g != G_TYPE_INVALID);
1435
1436                 s_base = g_object_new (type_g, NULL);
1437                 g_assert (NM_IS_SETTING (s_base));
1438         }
1439
1440 #if defined(__NM_SIMPLE_CONNECTION_H__)
1441         con = nm_simple_connection_new ();
1442 #else
1443         con = nm_connection_new ();
1444 #endif
1445
1446         s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
1447
1448         g_object_set (s_con,
1449                       NM_SETTING_CONNECTION_ID, id,
1450                       NM_SETTING_CONNECTION_UUID, uuid,
1451                       NM_SETTING_CONNECTION_TYPE, type,
1452                       NULL);
1453         nm_connection_add_setting (con, NM_SETTING (s_con));
1454
1455         if (s_base)
1456                 nm_connection_add_setting (con, s_base);
1457
1458         if (out_s_con)
1459                 *out_s_con = s_con;
1460         return con;
1461 }
1462
1463 inline static gboolean
1464 _nmtst_connection_normalize_v (NMConnection *connection, va_list args)
1465 {
1466         GError *error = NULL;
1467         gboolean success;
1468         gboolean was_modified = FALSE;
1469         GHashTable *parameters = NULL;
1470         const char *p_name;
1471
1472         g_assert (NM_IS_CONNECTION (connection));
1473
1474         while ((p_name = va_arg (args, const char *))) {
1475                 if (!parameters)
1476                         parameters =  g_hash_table_new (g_str_hash, g_str_equal);
1477                 g_hash_table_insert (parameters, (gpointer *) p_name, va_arg (args, gpointer));
1478         }
1479
1480         success = nm_connection_normalize (connection,
1481                                            parameters,
1482                                            &was_modified,
1483                                            &error);
1484         g_assert_no_error (error);
1485         g_assert (success);
1486
1487         if (parameters)
1488                 g_hash_table_destroy (parameters);
1489
1490         return was_modified;
1491 }
1492
1493 inline static gboolean
1494 _nmtst_connection_normalize (NMConnection *connection, ...)
1495 {
1496         gboolean was_modified;
1497         va_list args;
1498
1499         va_start (args, connection);
1500         was_modified = _nmtst_connection_normalize_v (connection, args);
1501         va_end (args);
1502
1503         return was_modified;
1504 }
1505 #define nmtst_connection_normalize(connection, ...) \
1506     _nmtst_connection_normalize(connection, ##__VA_ARGS__, NULL)
1507
1508 inline static NMConnection *
1509 _nmtst_connection_duplicate_and_normalize (NMConnection *connection, ...)
1510 {
1511         gboolean was_modified;
1512         va_list args;
1513
1514         connection = nmtst_clone_connection (connection);
1515
1516         va_start (args, connection);
1517         was_modified = _nmtst_connection_normalize_v (connection, args);
1518         va_end (args);
1519
1520         return connection;
1521 }
1522 #define nmtst_connection_duplicate_and_normalize(connection, ...) \
1523     _nmtst_connection_duplicate_and_normalize(connection, ##__VA_ARGS__, NULL)
1524
1525 inline static void
1526 nmtst_assert_connection_equals (NMConnection *a, gboolean normalize_a, NMConnection *b, gboolean normalize_b)
1527 {
1528         gboolean compare;
1529         gs_unref_object NMConnection *a2 = NULL;
1530         gs_unref_object NMConnection *b2 = NULL;
1531         GHashTable *out_settings = NULL;
1532
1533         g_assert (NM_IS_CONNECTION (a));
1534         g_assert (NM_IS_CONNECTION (b));
1535
1536         if (normalize_a)
1537                 a = a2 = nmtst_connection_duplicate_and_normalize (a);
1538         if (normalize_b)
1539                 b = b2 = nmtst_connection_duplicate_and_normalize (b);
1540
1541         compare = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_settings);
1542         if (!compare || out_settings) {
1543                 const char *name, *pname;
1544                 GHashTable *setting;
1545                 GHashTableIter iter, iter2;
1546
1547                 __NMTST_LOG (g_message, ">>> ASSERTION nmtst_assert_connection_equals() fails");
1548                 if (out_settings) {
1549                         g_hash_table_iter_init (&iter, out_settings);
1550                         while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &setting)) {
1551                                 __NMTST_LOG (g_message, ">>> differences in setting '%s':", name);
1552
1553                                 g_hash_table_iter_init (&iter2, setting);
1554                                 while (g_hash_table_iter_next (&iter2, (gpointer *) &pname, NULL))
1555                                         __NMTST_LOG (g_message, ">>> differences in setting '%s.%s'", name, pname);
1556                         }
1557                 }
1558
1559 #ifdef __NM_KEYFILE_INTERNAL_H__
1560                 {
1561                         gs_unref_keyfile GKeyFile *kf_a = NULL, *kf_b = NULL;
1562                         gs_free char *str_a = NULL, *str_b = NULL;
1563
1564                         kf_a = nm_keyfile_write (a, NULL, NULL, NULL);
1565                         kf_b = nm_keyfile_write (b, NULL, NULL, NULL);
1566
1567                         if (kf_a)
1568                                 str_a = g_key_file_to_data (kf_a, NULL, NULL);
1569                         if (kf_b)
1570                                 str_b = g_key_file_to_data (kf_b, NULL, NULL);
1571
1572                         __NMTST_LOG (g_message, ">>> Connection A as kf (*WARNING: keyfile representation might not show the difference*):\n%s", str_a);
1573                         __NMTST_LOG (g_message, ">>> Connection B as kf (*WARNING: keyfile representation might not show the difference*):\n%s", str_b);
1574                 }
1575 #endif
1576         }
1577         g_assert (compare);
1578         g_assert (!out_settings);
1579
1580         compare = nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT);
1581         g_assert (compare);
1582 }
1583
1584 inline static void
1585 nmtst_assert_connection_verifies (NMConnection *con)
1586 {
1587         /* assert that the connection does verify, it might be normaliziable or not */
1588         GError *error = NULL;
1589         gboolean success;
1590
1591         g_assert (NM_IS_CONNECTION (con));
1592
1593         success = nm_connection_verify (con, &error);
1594         g_assert_no_error (error);
1595         g_assert (success);
1596 }
1597
1598 inline static void
1599 nmtst_assert_connection_verifies_without_normalization (NMConnection *con)
1600 {
1601         /* assert that the connection verifies and does not need any normalization */
1602         GError *error = NULL;
1603         gboolean success;
1604         gboolean was_modified = FALSE;
1605         gs_unref_object NMConnection *clone = NULL;
1606
1607         clone = nmtst_clone_connection (con);
1608
1609         nmtst_assert_connection_verifies (con);
1610
1611         success = nm_connection_normalize (clone, NULL, &was_modified, &error);
1612         g_assert_no_error (error);
1613         g_assert (success);
1614         nmtst_assert_connection_equals (con, FALSE, clone, FALSE);
1615         g_assert (!was_modified);
1616 }
1617
1618 inline static void
1619 nmtst_assert_connection_verifies_and_normalizable (NMConnection *con)
1620 {
1621         /* assert that the connection does verify, but normalization still modifies it */
1622         GError *error = NULL;
1623         gboolean success;
1624         gboolean was_modified = FALSE;
1625         gs_unref_object NMConnection *clone = NULL;
1626
1627         clone = nmtst_clone_connection (con);
1628
1629         nmtst_assert_connection_verifies (con);
1630
1631         success = nm_connection_normalize (clone, NULL, &was_modified, &error);
1632         g_assert_no_error (error);
1633         g_assert (success);
1634         g_assert (was_modified);
1635
1636         /* again! */
1637         nmtst_assert_connection_verifies_without_normalization (clone);
1638 }
1639
1640 inline static void
1641 nmtst_assert_connection_verifies_after_normalization (NMConnection *con,
1642                                                       GQuark expect_error_domain,
1643                                                       gint expect_error_code)
1644 {
1645         /* assert that the connection does not verify, but normalization does fix it */
1646         GError *error = NULL;
1647         gboolean success;
1648         gboolean was_modified = FALSE;
1649         gs_unref_object NMConnection *clone = NULL;
1650
1651         clone = nmtst_clone_connection (con);
1652
1653         success = nm_connection_verify (con, &error);
1654         nmtst_assert_error (error, expect_error_domain, expect_error_code, NULL);
1655         g_assert (!success);
1656         g_clear_error (&error);
1657
1658         success = nm_connection_normalize (clone, NULL, &was_modified, &error);
1659         g_assert_no_error (error);
1660         g_assert (success);
1661         g_assert (was_modified);
1662
1663         /* again! */
1664         nmtst_assert_connection_verifies_without_normalization (clone);
1665 }
1666
1667 inline static void
1668 nmtst_assert_connection_unnormalizable (NMConnection *con,
1669                                         GQuark expect_error_domain,
1670                                         gint expect_error_code)
1671 {
1672         /* assert that the connection does not verify, and it cannot be fixed by normalization */
1673
1674         GError *error = NULL;
1675         gboolean success;
1676         gboolean was_modified = FALSE;
1677         gs_unref_object NMConnection *clone = NULL;
1678
1679         clone = nmtst_clone_connection (con);
1680
1681         success = nm_connection_verify (con, &error);
1682         nmtst_assert_error (error, expect_error_domain, expect_error_code, NULL);
1683         g_assert (!success);
1684         g_clear_error (&error);
1685
1686         success = nm_connection_normalize (clone, NULL, &was_modified, &error);
1687         nmtst_assert_error (error, expect_error_domain, expect_error_code, NULL);
1688         g_assert (!success);
1689         g_assert (!was_modified);
1690         nmtst_assert_connection_equals (con, FALSE, clone, FALSE);
1691         g_clear_error (&error);
1692 }
1693
1694 inline static void
1695 nmtst_assert_setting_verifies (NMSetting *setting)
1696 {
1697         /* assert that the setting verifies without an error */
1698
1699         GError *error = NULL;
1700         gboolean success;
1701
1702         g_assert (NM_IS_SETTING (setting));
1703
1704         success = nm_setting_verify (setting, NULL, &error);
1705         g_assert_no_error (error);
1706         g_assert (success);
1707 }
1708
1709 inline static void
1710 nmtst_assert_setting_verify_fails (NMSetting *setting,
1711                                    GQuark expect_error_domain,
1712                                    gint expect_error_code)
1713 {
1714         /* assert that the setting verification fails */
1715
1716         GError *error = NULL;
1717         gboolean success;
1718
1719         g_assert (NM_IS_SETTING (setting));
1720
1721         success = nm_setting_verify (setting, NULL, &error);
1722         nmtst_assert_error (error, expect_error_domain, expect_error_code, NULL);
1723         g_assert (!success);
1724         g_clear_error (&error);
1725 }
1726
1727 #endif
1728
1729 #ifdef __NM_UTILS_H__
1730 static inline void
1731 nmtst_assert_hwaddr_equals (gconstpointer hwaddr1, gssize hwaddr1_len, const char *expected, const char *file, int line)
1732 {
1733         guint8 buf2[NM_UTILS_HWADDR_LEN_MAX];
1734         gsize hwaddr2_len = 1;
1735         const char *p;
1736         gboolean success;
1737
1738         g_assert (hwaddr1_len > 0 && hwaddr1_len <= NM_UTILS_HWADDR_LEN_MAX);
1739
1740         g_assert (expected);
1741         for (p = expected; *p; p++) {
1742                 if (*p == ':' || *p == '-')
1743                         hwaddr2_len++;
1744         }
1745         g_assert (hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX);
1746         g_assert (nm_utils_hwaddr_aton (expected, buf2, hwaddr2_len));
1747
1748         /* Manually check the entire hardware address instead of using
1749          * nm_utils_hwaddr_matches() because that function doesn't compare
1750          * entire InfiniBand addresses for various (legitimate) reasons.
1751          */
1752         success = (hwaddr1_len == hwaddr2_len);
1753         if (success)
1754                 success = !memcmp (hwaddr1, buf2, hwaddr1_len);
1755         if (!success) {
1756                 g_error ("assert: %s:%d: hwaddr '%s' (%zd) expected, but got %s (%zd)",
1757                          file, line, expected, hwaddr2_len, nm_utils_hwaddr_ntoa (hwaddr1, hwaddr1_len), hwaddr1_len);
1758         }
1759 }
1760 #define nmtst_assert_hwaddr_equals(hwaddr1, hwaddr1_len, expected) \
1761     nmtst_assert_hwaddr_equals (hwaddr1, hwaddr1_len, expected, __FILE__, __LINE__)
1762 #endif
1763
1764 #if defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__) && defined(__NM_KEYFILE_INTERNAL_H__)
1765
1766 inline static NMConnection *
1767 nmtst_create_connection_from_keyfile (const char *keyfile_str, const char *keyfile_name, const char *base_dir)
1768 {
1769         GKeyFile *keyfile;
1770         GError *error = NULL;
1771         gboolean success;
1772         NMConnection *con;
1773
1774         g_assert (keyfile_str);
1775
1776         keyfile =  g_key_file_new ();
1777         success = g_key_file_load_from_data (keyfile, keyfile_str, strlen (keyfile_str), G_KEY_FILE_NONE, &error);
1778         g_assert_no_error (error);
1779         g_assert (success);
1780
1781         con = nm_keyfile_read (keyfile, keyfile_name, base_dir, NULL, NULL, &error);
1782         g_assert_no_error (error);
1783         g_assert (NM_IS_CONNECTION (con));
1784
1785         g_key_file_unref (keyfile);
1786
1787         nmtst_connection_normalize (con);
1788
1789         return con;
1790 }
1791
1792 #endif
1793
1794 #ifdef __NM_CONNECTION_H__
1795
1796 inline static GVariant *
1797 _nmtst_variant_new_vardict (int dummy, ...)
1798 {
1799         GVariantBuilder builder;
1800         va_list ap;
1801         const char *name;
1802         GVariant *variant;
1803
1804         g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
1805
1806         va_start (ap, dummy);
1807         while ((name = va_arg (ap, const char *))) {
1808                 variant = va_arg (ap, GVariant *);
1809                 g_variant_builder_add (&builder, "{sv}", name, variant);
1810         }
1811         va_end (ap);
1812
1813         return g_variant_builder_end (&builder);
1814 }
1815 #define nmtst_variant_new_vardict(...) _nmtst_variant_new_vardict (0, __VA_ARGS__, NULL)
1816
1817 #define nmtst_assert_variant_is_of_type(variant, type) \
1818         G_STMT_START { \
1819                 GVariant *_variantx = (variant); \
1820                 \
1821                 g_assert (_variantx); \
1822                 g_assert (g_variant_is_of_type (_variantx, (type))); \
1823         } G_STMT_END
1824
1825 #define nmtst_assert_variant_uint32(variant, val) \
1826         G_STMT_START { \
1827                 GVariant *_variant = (variant); \
1828                 \
1829                 nmtst_assert_variant_is_of_type (_variant, G_VARIANT_TYPE_UINT32); \
1830                 g_assert_cmpint (g_variant_get_uint32 (_variant), ==, (val)); \
1831         } G_STMT_END
1832
1833 #define nmtst_assert_variant_string(variant, str) \
1834         G_STMT_START { \
1835                 gsize _l; \
1836                 GVariant *_variant = (variant); \
1837                 const char *_str = (str); \
1838                 \
1839                 nmtst_assert_variant_is_of_type (_variant, G_VARIANT_TYPE_STRING); \
1840                 g_assert (_str); \
1841                 g_assert_cmpstr (g_variant_get_string (_variant, &_l), ==, _str); \
1842                 g_assert_cmpint (_l, ==, strlen (_str)); \
1843         } G_STMT_END
1844
1845 typedef enum {
1846         NMTST_VARIANT_EDITOR_CONNECTION,
1847         NMTST_VARIANT_EDITOR_SETTING,
1848         NMTST_VARIANT_EDITOR_PROPERTY
1849 } NmtstVariantEditorPhase;
1850
1851 #define NMTST_VARIANT_EDITOR(__connection_variant, __code) \
1852         G_STMT_START { \
1853                 GVariantIter __connection_iter, *__setting_iter; \
1854                 GVariantBuilder __connection_builder, __setting_builder; \
1855                 const char *__cur_setting_name, *__cur_property_name; \
1856                 GVariant *__property_val; \
1857                 NmtstVariantEditorPhase __phase; \
1858                                                                         \
1859                 g_variant_builder_init (&__connection_builder, NM_VARIANT_TYPE_CONNECTION); \
1860                 g_variant_iter_init (&__connection_iter, __connection_variant); \
1861                  \
1862                 __phase = NMTST_VARIANT_EDITOR_CONNECTION; \
1863                 __cur_setting_name = NULL; \
1864                 __cur_property_name = NULL; \
1865                 __code; \
1866                 while (g_variant_iter_next (&__connection_iter, "{&sa{sv}}", &__cur_setting_name, &__setting_iter)) { \
1867                         g_variant_builder_init (&__setting_builder, NM_VARIANT_TYPE_SETTING); \
1868                         __phase = NMTST_VARIANT_EDITOR_SETTING; \
1869                         __cur_property_name = NULL; \
1870                         __code; \
1871                          \
1872                         while (   __cur_setting_name \
1873                                && g_variant_iter_next (__setting_iter, "{&sv}", &__cur_property_name, &__property_val)) { \
1874                                 __phase = NMTST_VARIANT_EDITOR_PROPERTY; \
1875                                 __code; \
1876                                  \
1877                                 if (__cur_property_name) { \
1878                                         g_variant_builder_add (&__setting_builder, "{sv}", \
1879                                                                __cur_property_name, \
1880                                                                __property_val); \
1881                                 } \
1882                                 g_variant_unref (__property_val); \
1883                         } \
1884                          \
1885                         if (__cur_setting_name) \
1886                                 g_variant_builder_add (&__connection_builder, "{sa{sv}}", __cur_setting_name, &__setting_builder); \
1887                         else \
1888                                 g_variant_builder_clear (&__setting_builder); \
1889                         g_variant_iter_free (__setting_iter); \
1890                 } \
1891                  \
1892                 g_variant_unref (__connection_variant); \
1893                  \
1894                 __connection_variant = g_variant_builder_end (&__connection_builder); \
1895         } G_STMT_END;
1896
1897 #define NMTST_VARIANT_ADD_SETTING(__setting_name, __setting_variant) \
1898         G_STMT_START { \
1899                 if (__phase == NMTST_VARIANT_EDITOR_CONNECTION) \
1900                         g_variant_builder_add (&__connection_builder, "{s@a{sv}}", __setting_name, __setting_variant); \
1901         } G_STMT_END
1902
1903 #define NMTST_VARIANT_DROP_SETTING(__setting_name) \
1904         G_STMT_START { \
1905                 if (__phase == NMTST_VARIANT_EDITOR_SETTING && __cur_setting_name) { \
1906                         if (!strcmp (__cur_setting_name, __setting_name)) \
1907                                 __cur_setting_name = NULL; \
1908                 } \
1909         } G_STMT_END
1910
1911 #define NMTST_VARIANT_ADD_PROPERTY(__setting_name, __property_name, __format_string, __value) \
1912         G_STMT_START { \
1913                 if (__phase == NMTST_VARIANT_EDITOR_SETTING) { \
1914                         if (!strcmp (__cur_setting_name, __setting_name)) { \
1915                                 g_variant_builder_add (&__setting_builder, "{sv}", __property_name, \
1916                                                        g_variant_new (__format_string, __value)); \
1917                         } \
1918                 } \
1919         } G_STMT_END
1920
1921 #define NMTST_VARIANT_DROP_PROPERTY(__setting_name, __property_name) \
1922         G_STMT_START { \
1923                 if (__phase == NMTST_VARIANT_EDITOR_PROPERTY && __cur_property_name) { \
1924                         if (   !strcmp (__cur_setting_name, __setting_name) \
1925                             && !strcmp (__cur_property_name, __property_name)) \
1926                                 __cur_property_name = NULL; \
1927                 } \
1928         } G_STMT_END
1929
1930 #define NMTST_VARIANT_CHANGE_PROPERTY(__setting_name, __property_name, __format_string, __value) \
1931         G_STMT_START { \
1932                 NMTST_VARIANT_DROP_PROPERTY (__setting_name, __property_name); \
1933                 NMTST_VARIANT_ADD_PROPERTY (__setting_name, __property_name, __format_string, __value); \
1934         } G_STMT_END
1935
1936 #endif /* __NM_CONNECTION_H__ */
1937
1938 #endif /* __NM_TEST_UTILS_H__ */