1 #include <stdlib.h>
2 #include <string.h>
3 #define G_LOG_USE_STRUCTURED 1
4 #include <glib.h>
5 
6 /* Test g_warn macros */
7 static void
test_warnings(void)8 test_warnings (void)
9 {
10   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
11                          "*test_warnings*should not be reached*");
12   g_warn_if_reached ();
13   g_test_assert_expected_messages ();
14 
15   g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
16                          "*test_warnings*runtime check failed*");
17   g_warn_if_fail (FALSE);
18   g_test_assert_expected_messages ();
19 }
20 
21 static guint log_count = 0;
22 
23 static void
log_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer user_data)24 log_handler (const gchar    *log_domain,
25              GLogLevelFlags  log_level,
26              const gchar    *message,
27              gpointer        user_data)
28 {
29   g_assert_cmpstr (log_domain, ==, "bu");
30   g_assert_cmpint (log_level, ==, G_LOG_LEVEL_INFO);
31 
32   log_count++;
33 }
34 
35 /* test that custom log handlers only get called for
36  * their domain and level
37  */
38 static void
test_set_handler(void)39 test_set_handler (void)
40 {
41   guint id;
42 
43   id = g_log_set_handler ("bu", G_LOG_LEVEL_INFO, log_handler, NULL);
44 
45   g_log ("bu", G_LOG_LEVEL_DEBUG, "message");
46   g_log ("ba", G_LOG_LEVEL_DEBUG, "message");
47   g_log ("bu", G_LOG_LEVEL_INFO, "message");
48   g_log ("ba", G_LOG_LEVEL_INFO, "message");
49 
50   g_assert_cmpint (log_count, ==, 1);
51 
52   g_log_remove_handler ("bu", id);
53 }
54 
55 static void
test_default_handler_error(void)56 test_default_handler_error (void)
57 {
58   g_log_set_default_handler (g_log_default_handler, NULL);
59   g_error ("message1");
60   exit (0);
61 }
62 
63 static void
test_default_handler_critical(void)64 test_default_handler_critical (void)
65 {
66   g_log_set_default_handler (g_log_default_handler, NULL);
67   g_critical ("message2");
68   exit (0);
69 }
70 
71 static void
test_default_handler_warning(void)72 test_default_handler_warning (void)
73 {
74   g_log_set_default_handler (g_log_default_handler, NULL);
75   g_warning ("message3");
76   exit (0);
77 }
78 
79 static void
test_default_handler_message(void)80 test_default_handler_message (void)
81 {
82   g_log_set_default_handler (g_log_default_handler, NULL);
83   g_message ("message4");
84   exit (0);
85 }
86 
87 static void
test_default_handler_info(void)88 test_default_handler_info (void)
89 {
90   g_log_set_default_handler (g_log_default_handler, NULL);
91   g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "message5");
92   exit (0);
93 }
94 
95 static void
test_default_handler_bar_info(void)96 test_default_handler_bar_info (void)
97 {
98   g_log_set_default_handler (g_log_default_handler, NULL);
99 
100   g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE);
101 
102   g_log ("bar", G_LOG_LEVEL_INFO, "message5");
103   exit (0);
104 }
105 
106 static void
test_default_handler_baz_debug(void)107 test_default_handler_baz_debug (void)
108 {
109   g_log_set_default_handler (g_log_default_handler, NULL);
110 
111   g_setenv ("G_MESSAGES_DEBUG", "foo bar baz", TRUE);
112 
113   g_log ("baz", G_LOG_LEVEL_DEBUG, "message6");
114   exit (0);
115 }
116 
117 static void
test_default_handler_debug(void)118 test_default_handler_debug (void)
119 {
120   g_log_set_default_handler (g_log_default_handler, NULL);
121 
122   g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
123 
124   g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
125   g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
126   g_log ("baz", G_LOG_LEVEL_DEBUG, "6");
127 
128   exit (0);
129 }
130 
131 static void
test_default_handler_debug_stderr(void)132 test_default_handler_debug_stderr (void)
133 {
134   g_log_writer_default_set_use_stderr (TRUE);
135   g_log_set_default_handler (g_log_default_handler, NULL);
136 
137   g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
138 
139   g_log ("foo", G_LOG_LEVEL_DEBUG, "6");
140   g_log ("bar", G_LOG_LEVEL_DEBUG, "6");
141   g_log ("baz", G_LOG_LEVEL_DEBUG, "6");
142 
143   exit (0);
144 }
145 
146 static void
test_default_handler_would_drop(void)147 test_default_handler_would_drop (void)
148 {
149   g_unsetenv ("G_MESSAGES_DEBUG");
150 
151   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
152   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
153   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
154   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
155   g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
156   g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
157   g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
158 
159   g_setenv ("G_MESSAGES_DEBUG", "bar baz", TRUE);
160 
161   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
162   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
163   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
164   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
165   g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
166   g_assert_true (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
167   g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
168 
169   g_setenv ("G_MESSAGES_DEBUG", "foo bar", TRUE);
170 
171   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
172   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
173   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
174   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
175   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
176   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
177   g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
178 
179   g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
180 
181   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_ERROR, "foo"));
182   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_CRITICAL, "foo"));
183   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_WARNING, "foo"));
184   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_MESSAGE, "foo"));
185   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_INFO, "foo"));
186   g_assert_false (g_log_writer_default_would_drop (G_LOG_LEVEL_DEBUG, "foo"));
187   g_assert_false (g_log_writer_default_would_drop (1<<G_LOG_LEVEL_USER_SHIFT, "foo"));
188 
189   exit (0);
190 }
191 
192 static void
test_default_handler_0x400(void)193 test_default_handler_0x400 (void)
194 {
195   g_log_set_default_handler (g_log_default_handler, NULL);
196   g_log (G_LOG_DOMAIN, 1<<10, "message7");
197   exit (0);
198 }
199 
200 static void
test_default_handler(void)201 test_default_handler (void)
202 {
203   g_test_trap_subprocess ("/logging/default-handler/subprocess/error", 0, 0);
204   g_test_trap_assert_failed ();
205   g_test_trap_assert_stderr ("*ERROR*message1*");
206 
207   g_test_trap_subprocess ("/logging/default-handler/subprocess/critical", 0, 0);
208   g_test_trap_assert_failed ();
209   g_test_trap_assert_stderr ("*CRITICAL*message2*");
210 
211   g_test_trap_subprocess ("/logging/default-handler/subprocess/warning", 0, 0);
212   g_test_trap_assert_failed ();
213   g_test_trap_assert_stderr ("*WARNING*message3*");
214 
215   g_test_trap_subprocess ("/logging/default-handler/subprocess/message", 0, 0);
216   g_test_trap_assert_passed ();
217   g_test_trap_assert_stderr ("*Message*message4*");
218 
219   g_test_trap_subprocess ("/logging/default-handler/subprocess/info", 0, 0);
220   g_test_trap_assert_passed ();
221   g_test_trap_assert_stdout_unmatched ("*INFO*message5*");
222 
223   g_test_trap_subprocess ("/logging/default-handler/subprocess/bar-info", 0, 0);
224   g_test_trap_assert_passed ();
225   g_test_trap_assert_stdout ("*INFO*message5*");
226 
227   g_test_trap_subprocess ("/logging/default-handler/subprocess/baz-debug", 0, 0);
228   g_test_trap_assert_passed ();
229   g_test_trap_assert_stdout ("*DEBUG*message6*");
230 
231   g_test_trap_subprocess ("/logging/default-handler/subprocess/debug", 0, 0);
232   g_test_trap_assert_passed ();
233   g_test_trap_assert_stdout ("*DEBUG*6*6*6*");
234 
235   g_test_trap_subprocess ("/logging/default-handler/subprocess/debug-stderr", 0, 0);
236   g_test_trap_assert_passed ();
237   g_test_trap_assert_stdout_unmatched ("DEBUG");
238   g_test_trap_assert_stderr ("*DEBUG*6*6*6*");
239 
240   g_test_trap_subprocess ("/logging/default-handler/subprocess/0x400", 0, 0);
241   g_test_trap_assert_passed ();
242   g_test_trap_assert_stdout ("*LOG-0x400*message7*");
243 
244   g_test_trap_subprocess ("/logging/default-handler/subprocess/would-drop", 0, 0);
245   g_test_trap_assert_passed ();
246 }
247 
248 static void
test_fatal_log_mask(void)249 test_fatal_log_mask (void)
250 {
251   if (g_test_subprocess ())
252     {
253       g_log_set_fatal_mask ("bu", G_LOG_LEVEL_INFO);
254       g_log ("bu", G_LOG_LEVEL_INFO, "fatal");
255       return;
256     }
257   g_test_trap_subprocess (NULL, 0, 0);
258   g_test_trap_assert_failed ();
259   /* G_LOG_LEVEL_INFO isn't printed by default */
260   g_test_trap_assert_stdout_unmatched ("*fatal*");
261 }
262 
263 static gint my_print_count = 0;
264 static void
my_print_handler(const gchar * text)265 my_print_handler (const gchar *text)
266 {
267   my_print_count++;
268 }
269 
270 static void
test_print_handler(void)271 test_print_handler (void)
272 {
273   GPrintFunc old_print_handler;
274 
275   old_print_handler = g_set_print_handler (my_print_handler);
276   g_assert (old_print_handler == NULL);
277 
278   my_print_count = 0;
279   g_print ("bu ba");
280   g_assert_cmpint (my_print_count, ==, 1);
281 
282   g_set_print_handler (NULL);
283 }
284 
285 static void
test_printerr_handler(void)286 test_printerr_handler (void)
287 {
288   GPrintFunc old_printerr_handler;
289 
290   old_printerr_handler = g_set_printerr_handler (my_print_handler);
291   g_assert (old_printerr_handler == NULL);
292 
293   my_print_count = 0;
294   g_printerr ("bu ba");
295   g_assert_cmpint (my_print_count, ==, 1);
296 
297   g_set_printerr_handler (NULL);
298 }
299 
300 static char *fail_str = "foo";
301 static char *log_str = "bar";
302 
303 static gboolean
good_failure_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * msg,gpointer user_data)304 good_failure_handler (const gchar    *log_domain,
305                       GLogLevelFlags  log_level,
306                       const gchar    *msg,
307                       gpointer        user_data)
308 {
309   g_test_message ("The Good Fail Message Handler\n");
310   g_assert ((char *)user_data != log_str);
311   g_assert ((char *)user_data == fail_str);
312 
313   return FALSE;
314 }
315 
316 static gboolean
bad_failure_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * msg,gpointer user_data)317 bad_failure_handler (const gchar    *log_domain,
318                      GLogLevelFlags  log_level,
319                      const gchar    *msg,
320                      gpointer        user_data)
321 {
322   g_test_message ("The Bad Fail Message Handler\n");
323   g_assert ((char *)user_data == log_str);
324   g_assert ((char *)user_data != fail_str);
325 
326   return FALSE;
327 }
328 
329 static void
test_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * msg,gpointer user_data)330 test_handler (const gchar    *log_domain,
331               GLogLevelFlags  log_level,
332               const gchar    *msg,
333               gpointer        user_data)
334 {
335   g_test_message ("The Log Message Handler\n");
336   g_assert ((char *)user_data != fail_str);
337   g_assert ((char *)user_data == log_str);
338 }
339 
340 static void
bug653052(void)341 bug653052 (void)
342 {
343   g_test_bug ("https://bugzilla.gnome.org/show_bug.cgi?id=653052");
344 
345   g_test_log_set_fatal_handler (good_failure_handler, fail_str);
346   g_log_set_default_handler (test_handler, log_str);
347 
348   g_return_if_fail (0);
349 
350   g_test_log_set_fatal_handler (bad_failure_handler, fail_str);
351   g_log_set_default_handler (test_handler, log_str);
352 
353   g_return_if_fail (0);
354 }
355 
356 static void
test_gibberish(void)357 test_gibberish (void)
358 {
359   if (g_test_subprocess ())
360     {
361       g_warning ("bla bla \236\237\190");
362       return;
363     }
364   g_test_trap_subprocess (NULL, 0, 0);
365   g_test_trap_assert_failed ();
366   g_test_trap_assert_stderr ("*bla bla \\x9e\\x9f\\u000190*");
367 }
368 
369 static GLogWriterOutput
null_log_writer(GLogLevelFlags log_level,const GLogField * fields,gsize n_fields,gpointer user_data)370 null_log_writer (GLogLevelFlags   log_level,
371                  const GLogField *fields,
372                  gsize            n_fields,
373                  gpointer         user_data)
374 {
375   log_count++;
376   return G_LOG_WRITER_HANDLED;
377 }
378 
379 typedef struct {
380   const GLogField *fields;
381   gsize n_fields;
382 } ExpectedMessage;
383 
384 static gboolean
compare_field(const GLogField * f1,const GLogField * f2)385 compare_field (const GLogField *f1, const GLogField *f2)
386 {
387   if (strcmp (f1->key, f2->key) != 0)
388     return FALSE;
389   if (f1->length != f2->length)
390     return FALSE;
391 
392   if (f1->length == -1)
393     return strcmp (f1->value, f2->value) == 0;
394   else
395     return memcmp (f1->value, f2->value, f1->length) == 0;
396 }
397 
398 static gboolean
compare_fields(const GLogField * f1,gsize n1,const GLogField * f2,gsize n2)399 compare_fields (const GLogField *f1, gsize n1, const GLogField *f2, gsize n2)
400 {
401   gsize i, j;
402 
403   for (i = 0; i < n1; i++)
404     {
405       for (j = 0; j < n2; j++)
406         {
407           if (compare_field (&f1[i], &f2[j]))
408             break;
409         }
410       if (j == n2)
411         return FALSE;
412     }
413 
414   return TRUE;
415 }
416 
417 static GSList *expected_messages = NULL;
418 static const guchar binary_field[] = {1, 2, 3, 4, 5};
419 
420 
421 static GLogWriterOutput
expect_log_writer(GLogLevelFlags log_level,const GLogField * fields,gsize n_fields,gpointer user_data)422 expect_log_writer (GLogLevelFlags   log_level,
423                    const GLogField *fields,
424                    gsize            n_fields,
425                    gpointer         user_data)
426 {
427   ExpectedMessage *expected = expected_messages->data;
428 
429   if (compare_fields (fields, n_fields, expected->fields, expected->n_fields))
430     {
431       expected_messages = g_slist_delete_link (expected_messages, expected_messages);
432     }
433   else if ((log_level & G_LOG_LEVEL_DEBUG) != G_LOG_LEVEL_DEBUG)
434     {
435       char *str;
436 
437       str = g_log_writer_format_fields (log_level, fields, n_fields, FALSE);
438       g_test_fail_printf ("Unexpected message: %s", str);
439       g_free (str);
440     }
441 
442   return G_LOG_WRITER_HANDLED;
443 }
444 
445 static void
test_structured_logging_no_state(void)446 test_structured_logging_no_state (void)
447 {
448   gpointer some_pointer = GUINT_TO_POINTER (0x100);
449   guint some_integer = 123;
450 
451   log_count = 0;
452   g_log_set_writer_func (null_log_writer, NULL, NULL);
453 
454   g_log_structured ("some-domain", G_LOG_LEVEL_MESSAGE,
455                     "MESSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e",
456                     "MY_APPLICATION_CUSTOM_FIELD", "some debug string",
457                     "MESSAGE", "This is a debug message about pointer %p and integer %u.",
458                     some_pointer, some_integer);
459 
460   g_assert_cmpint (log_count, ==, 1);
461 }
462 
463 static void
test_structured_logging_some_state(void)464 test_structured_logging_some_state (void)
465 {
466   gpointer state_object = NULL;  /* this must not be dereferenced */
467   const GLogField fields[] = {
468     { "MESSAGE", "This is a debug message.", -1 },
469     { "MESSAGE_ID", "fcfb2e1e65c3494386b74878f1abf893", -1 },
470     { "MY_APPLICATION_CUSTOM_FIELD", "some debug string", -1 },
471     { "MY_APPLICATION_STATE", state_object, 0 },
472   };
473 
474   log_count = 0;
475   g_log_set_writer_func (null_log_writer, NULL, NULL);
476 
477   g_log_structured_array (G_LOG_LEVEL_DEBUG, fields, G_N_ELEMENTS (fields));
478 
479   g_assert_cmpint (log_count, ==, 1);
480 }
481 
482 static void
test_structured_logging_robustness(void)483 test_structured_logging_robustness (void)
484 {
485   log_count = 0;
486   g_log_set_writer_func (null_log_writer, NULL, NULL);
487 
488   /* NULL log_domain shouldn't crash */
489   g_log (NULL, G_LOG_LEVEL_MESSAGE, "Test");
490   g_log_structured (NULL, G_LOG_LEVEL_MESSAGE, "MESSAGE", "Test");
491 
492   g_assert_cmpint (log_count, ==, 1);
493 }
494 
495 static void
test_structured_logging_roundtrip1(void)496 test_structured_logging_roundtrip1 (void)
497 {
498   gpointer some_pointer = GUINT_TO_POINTER (0x100);
499   gint some_integer = 123;
500   gchar message[200];
501   GLogField fields[] = {
502     { "GLIB_DOMAIN", "some-domain", -1 },
503     { "PRIORITY", "5", -1 },
504     { "MESSAGE", "String assigned using g_snprintf() below", -1 },
505     { "MESSAGE_ID", "fcfb2e1e65c3494386b74878f1abf893", -1 },
506     { "MY_APPLICATION_CUSTOM_FIELD", "some debug string", -1 }
507   };
508   ExpectedMessage expected = { fields, 5 };
509 
510   /* %p format is implementation defined and depends on the platform */
511   g_snprintf (message, sizeof (message),
512               "This is a debug message about pointer %p and integer %u.",
513               some_pointer, some_integer);
514   fields[2].value = message;
515 
516   expected_messages = g_slist_append (NULL, &expected);
517   g_log_set_writer_func (expect_log_writer, NULL, NULL);
518 
519   g_log_structured ("some-domain", G_LOG_LEVEL_MESSAGE,
520                     "MESSAGE_ID", "fcfb2e1e65c3494386b74878f1abf893",
521                     "MY_APPLICATION_CUSTOM_FIELD", "some debug string",
522                     "MESSAGE", "This is a debug message about pointer %p and integer %u.",
523                     some_pointer, some_integer);
524 
525   if (expected_messages != NULL)
526     {
527       char *str;
528       ExpectedMessage *expected = expected_messages->data;
529 
530       str = g_log_writer_format_fields (0, expected->fields, expected->n_fields, FALSE);
531       g_test_fail_printf ("Unexpected message: %s", str);
532       g_free (str);
533     }
534 }
535 
536 static void
test_structured_logging_roundtrip2(void)537 test_structured_logging_roundtrip2 (void)
538 {
539   const gchar *some_string = "abc";
540   const GLogField fields[] = {
541     { "GLIB_DOMAIN", "some-domain", -1 },
542     { "PRIORITY", "5", -1 },
543     { "MESSAGE", "This is a debug message about string 'abc'.", -1 },
544     { "MESSAGE_ID", "fcfb2e1e65c3494386b74878f1abf893", -1 },
545     { "MY_APPLICATION_CUSTOM_FIELD", "some debug string", -1 }
546   };
547   ExpectedMessage expected = { fields, 5 };
548 
549   expected_messages = g_slist_append (NULL, &expected);
550   g_log_set_writer_func (expect_log_writer, NULL, NULL);
551 
552   g_log_structured ("some-domain", G_LOG_LEVEL_MESSAGE,
553                     "MESSAGE_ID", "fcfb2e1e65c3494386b74878f1abf893",
554                     "MY_APPLICATION_CUSTOM_FIELD", "some debug string",
555                     "MESSAGE", "This is a debug message about string '%s'.",
556                     some_string);
557 
558   g_assert (expected_messages == NULL);
559 }
560 
561 static void
test_structured_logging_roundtrip3(void)562 test_structured_logging_roundtrip3 (void)
563 {
564   const GLogField fields[] = {
565     { "GLIB_DOMAIN", "some-domain", -1 },
566     { "PRIORITY", "4", -1 },
567     { "MESSAGE", "Test test test.", -1 }
568   };
569   ExpectedMessage expected = { fields, 3 };
570 
571   expected_messages = g_slist_append (NULL, &expected);
572   g_log_set_writer_func (expect_log_writer, NULL, NULL);
573 
574   g_log_structured ("some-domain", G_LOG_LEVEL_WARNING,
575                     "MESSAGE", "Test test test.");
576 
577   g_assert (expected_messages == NULL);
578 }
579 
580 static GVariant *
create_variant_fields(void)581 create_variant_fields (void)
582 {
583   GVariant *binary;
584   GVariantBuilder builder;
585 
586   binary = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, binary_field, G_N_ELEMENTS (binary_field), sizeof (binary_field[0]));
587 
588   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
589   g_variant_builder_add (&builder, "{sv}", "MESSAGE_ID", g_variant_new_string ("06d4df59e6c24647bfe69d2c27ef0b4e"));
590   g_variant_builder_add (&builder, "{sv}", "MESSAGE", g_variant_new_string ("This is a debug message"));
591   g_variant_builder_add (&builder, "{sv}", "MY_APPLICATION_CUSTOM_FIELD", g_variant_new_string ("some debug string"));
592   g_variant_builder_add (&builder, "{sv}", "MY_APPLICATION_CUSTOM_FIELD_BINARY", binary);
593 
594   return g_variant_builder_end (&builder);
595 }
596 
597 static void
test_structured_logging_variant1(void)598 test_structured_logging_variant1 (void)
599 {
600   GVariant *v = create_variant_fields ();
601 
602   log_count = 0;
603   g_log_set_writer_func (null_log_writer, NULL, NULL);
604 
605   g_log_variant ("some-domain", G_LOG_LEVEL_MESSAGE, v);
606   g_variant_unref (v);
607   g_assert_cmpint (log_count, ==, 1);
608 }
609 
610 static void
test_structured_logging_variant2(void)611 test_structured_logging_variant2 (void)
612 {
613   const GLogField fields[] = {
614     { "GLIB_DOMAIN", "some-domain", -1 },
615     { "PRIORITY", "5", -1 },
616     { "MESSAGE", "This is a debug message", -1 },
617     { "MESSAGE_ID", "06d4df59e6c24647bfe69d2c27ef0b4e", -1 },
618     { "MY_APPLICATION_CUSTOM_FIELD", "some debug string", -1 },
619     { "MY_APPLICATION_CUSTOM_FIELD_BINARY", binary_field, sizeof (binary_field) }
620   };
621   ExpectedMessage expected = { fields, 6 };
622   GVariant *v = create_variant_fields ();
623 
624   expected_messages = g_slist_append (NULL, &expected);
625   g_log_set_writer_func (expect_log_writer, NULL, NULL);
626 
627   g_log_variant ("some-domain", G_LOG_LEVEL_MESSAGE, v);
628   g_variant_unref (v);
629   g_assert (expected_messages == NULL);
630 }
631 
632 int
main(int argc,char * argv[])633 main (int argc, char *argv[])
634 {
635   g_unsetenv ("G_MESSAGES_DEBUG");
636 
637   g_test_init (&argc, &argv, NULL);
638 
639   g_test_add_func ("/logging/default-handler", test_default_handler);
640   g_test_add_func ("/logging/default-handler/subprocess/error", test_default_handler_error);
641   g_test_add_func ("/logging/default-handler/subprocess/critical", test_default_handler_critical);
642   g_test_add_func ("/logging/default-handler/subprocess/warning", test_default_handler_warning);
643   g_test_add_func ("/logging/default-handler/subprocess/message", test_default_handler_message);
644   g_test_add_func ("/logging/default-handler/subprocess/info", test_default_handler_info);
645   g_test_add_func ("/logging/default-handler/subprocess/bar-info", test_default_handler_bar_info);
646   g_test_add_func ("/logging/default-handler/subprocess/baz-debug", test_default_handler_baz_debug);
647   g_test_add_func ("/logging/default-handler/subprocess/debug", test_default_handler_debug);
648   g_test_add_func ("/logging/default-handler/subprocess/debug-stderr", test_default_handler_debug_stderr);
649   g_test_add_func ("/logging/default-handler/subprocess/0x400", test_default_handler_0x400);
650   g_test_add_func ("/logging/default-handler/subprocess/would-drop", test_default_handler_would_drop);
651   g_test_add_func ("/logging/warnings", test_warnings);
652   g_test_add_func ("/logging/fatal-log-mask", test_fatal_log_mask);
653   g_test_add_func ("/logging/set-handler", test_set_handler);
654   g_test_add_func ("/logging/print-handler", test_print_handler);
655   g_test_add_func ("/logging/printerr-handler", test_printerr_handler);
656   g_test_add_func ("/logging/653052", bug653052);
657   g_test_add_func ("/logging/gibberish", test_gibberish);
658   g_test_add_func ("/structured-logging/no-state", test_structured_logging_no_state);
659   g_test_add_func ("/structured-logging/some-state", test_structured_logging_some_state);
660   g_test_add_func ("/structured-logging/robustness", test_structured_logging_robustness);
661   g_test_add_func ("/structured-logging/roundtrip1", test_structured_logging_roundtrip1);
662   g_test_add_func ("/structured-logging/roundtrip2", test_structured_logging_roundtrip2);
663   g_test_add_func ("/structured-logging/roundtrip3", test_structured_logging_roundtrip3);
664   g_test_add_func ("/structured-logging/variant1", test_structured_logging_variant1);
665   g_test_add_func ("/structured-logging/variant2", test_structured_logging_variant2);
666 
667   return g_test_run ();
668 }
669