1 /* Copyright (c) 2018 Dovecot authors, see the included COPYING file */
2 
3 #include "test-lib.h"
4 #include "ioloop.h"
5 #include "str.h"
6 #include "failures-private.h"
7 
8 #include <unistd.h>
9 
10 enum test_log_event_type {
11 	TYPE_END,
12 	TYPE_PREFIX_APPEND,
13 	TYPE_PREFIX_REPLACE,
14 	TYPE_PREFIX_APPEND_CB,
15 	TYPE_PREFIX_REPLACE_CB,
16 	TYPE_MESSAGE_AMEND,
17 	TYPE_SKIP,
18 };
19 
20 enum test_log_event_flag {
21 	FLAG_BASE_EVENT = BIT(0),
22 	FLAG_DROP_PREFIXES_1 = BIT(1),
23 	FLAG_DROP_PREFIXES_2 = BIT(2),
24 	FLAG_DROP_PREFIXES_4 = BIT(3),
25 };
26 
27 enum test_log_flag {
28 	FLAG_NO_SEND = BIT(0),
29 };
30 
31 struct test_log_event {
32 	enum test_log_event_type type;
33 	const char *str;
34 	enum test_log_event_flag flags;
35 };
36 
37 struct test_log {
38 	const struct test_log_event *prefixes;
39 	const char *global_log_prefix;
40 	const char *base_send_prefix;
41 	const char *base_str_prefix;
42 	const char *result;
43 	const char *result_str_out;
44 	enum test_log_flag flags;
45 };
46 
47 static char *test_output = NULL;
48 
49 static void ATTR_FORMAT(2, 0)
info_handler(const struct failure_context * ctx,const char * format,va_list args)50 info_handler(const struct failure_context *ctx,
51 	     const char *format, va_list args)
52 {
53 	size_t prefix_len;
54 
55 	i_assert(ctx->type == LOG_TYPE_INFO);
56 
57 	i_free(test_output);
58 	T_BEGIN {
59 		string_t *str = failure_handler.v->format(ctx, &prefix_len,
60 							  format, args);
61 		test_output = i_strdup(str_c(str));
62 	} T_END;
63 }
64 
65 static void ATTR_FORMAT(2, 0)
error_handler(const struct failure_context * ctx,const char * format,va_list args)66 error_handler(const struct failure_context *ctx,
67 	     const char *format, va_list args)
68 {
69 	size_t prefix_len;
70 
71 	i_assert(ctx->type == LOG_TYPE_WARNING ||
72 		 ctx->type == LOG_TYPE_ERROR);
73 
74 	i_free(test_output);
75 	T_BEGIN {
76 		string_t *str = failure_handler.v->format(ctx, &prefix_len,
77 							  format, args);
78 		test_output = i_strdup(str_c(str));
79 	} T_END;
80 }
81 
82 static const char *
test_event_log_prefix_cb(char * prefix)83 test_event_log_prefix_cb(char *prefix)
84 {
85 	return t_strdup_printf("callback(%s)", prefix);
86 }
87 
88 static const char *
test_event_log_message_cb(char * prefix,enum log_type log_type ATTR_UNUSED,const char * message)89 test_event_log_message_cb(char *prefix,
90 			  enum log_type log_type ATTR_UNUSED,
91 			  const char *message)
92 {
93 	return t_strdup_printf("[%s%s]", prefix, message);
94 }
95 
test_event_log_message(void)96 static void test_event_log_message(void)
97 {
98 	struct test_log tests[] = {
99 		{
100 			.prefixes = (const struct test_log_event []) {
101 				{ .type = TYPE_END }
102 			},
103 			.global_log_prefix = "global1.",
104 			.result = "global1.Info: TEXT",
105 		},
106 		{
107 			.prefixes = (const struct test_log_event []) {
108 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
109 				{ .type = TYPE_END }
110 			},
111 			.result = "replaced1,Info: TEXT",
112 		},
113 		{
114 			.prefixes = (const struct test_log_event []) {
115 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
116 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
117 				{ .type = TYPE_END }
118 			},
119 			.result = "replaced2.Info: TEXT",
120 		},
121 		{
122 			.prefixes = (const struct test_log_event []) {
123 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
124 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
125 				{ .type = TYPE_END }
126 			},
127 			.result = "replaced1,Info: appended2.TEXT",
128 		},
129 		{
130 			.prefixes = (const struct test_log_event []) {
131 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
132 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
133 				{ .type = TYPE_END }
134 			},
135 			.result = "replaced1,Info: TEXT",
136 		},
137 		{
138 			.prefixes = (const struct test_log_event []) {
139 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
140 				{ .type = TYPE_END }
141 			},
142 			.global_log_prefix = "global2.",
143 			.result = "global2.Info: appended1,TEXT",
144 		},
145 		{
146 			.prefixes = (const struct test_log_event []) {
147 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
148 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
149 				{ .type = TYPE_END }
150 			},
151 			.global_log_prefix = "global3.",
152 			.result = "global3.Info: appended1,appended2.TEXT",
153 		},
154 		{
155 			.prefixes = (const struct test_log_event []) {
156 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
157 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
158 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
159 				{ .type = TYPE_END }
160 			},
161 			.global_log_prefix = "global3.",
162 			.result = "global3.Info: "
163 				  "appended1,appended2.appended3.TEXT",
164 		},
165 		{
166 			.prefixes = (const struct test_log_event []) {
167 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
168 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
169 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
170 				{ .type = TYPE_END }
171 			},
172 			.result = "replaced2.Info: appended3#TEXT",
173 		},
174 		{
175 			.prefixes = (const struct test_log_event []) {
176 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
177 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
178 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
179 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
180 				{ .type = TYPE_END }
181 			},
182 			.result = "replaced4;Info: TEXT",
183 		},
184 		{
185 			.prefixes = (const struct test_log_event []) {
186 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
187 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
188 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
189 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
190 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
191 				{ .type = TYPE_END }
192 			},
193 			.result = "replaced4;Info: appended5-TEXT",
194 		},
195 		{
196 			.prefixes = (const struct test_log_event []) {
197 				{ TYPE_PREFIX_APPEND_CB, "appended1-", 0 },
198 				{ .type = TYPE_END }
199 			},
200 			.global_log_prefix = "global3.",
201 			.result = "global3.Info: callback(appended1-)TEXT",
202 		},
203 		{
204 			.prefixes = (const struct test_log_event []) {
205 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
206 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
207 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
208 				{ .type = TYPE_END }
209 			},
210 			.result = "callback(replaced2-)Info: TEXT",
211 		},
212 		{
213 			.prefixes = (const struct test_log_event []) {
214 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
215 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
216 				{ .type = TYPE_END }
217 			},
218 			.result = "callback(replaced1.)Info: appended1,TEXT",
219 		},
220 		{
221 			.prefixes = (const struct test_log_event []) {
222 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
223 				{ TYPE_PREFIX_REPLACE, "replaced2-", 0 },
224 				{ .type = TYPE_END }
225 			},
226 			.result = "replaced2-Info: TEXT",
227 		},
228 		/* Tests involving event_set_log_message_callback() */
229 		{
230 			.prefixes = (const struct test_log_event []) {
231 				{ TYPE_MESSAGE_AMEND, "amended1-" , 0},
232 				{ .type = TYPE_END }
233 			},
234 			.global_log_prefix = "global4.",
235 			.result = "global4.Info: [amended1-TEXT]",
236 		},
237 		{
238 			.prefixes = (const struct test_log_event []) {
239 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
240 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
241 				{ .type = TYPE_END }
242 			},
243 			.global_log_prefix = "global4.",
244 			.result = "global4.Info: [amended1-[amended2-TEXT]]",
245 		},
246 		{
247 			.prefixes = (const struct test_log_event []) {
248 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
249 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
250 				{ .type = TYPE_END }
251 			},
252 			.global_log_prefix = "global4.",
253 			.result = "global4.Info: [amended1-appended1-TEXT]",
254 		},
255 		{
256 			.prefixes = (const struct test_log_event []) {
257 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
258 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
259 				{ .type = TYPE_END }
260 			},
261 			.global_log_prefix = "global4.",
262 			.result = "global4.Info: appended1-[amended1-TEXT]",
263 		},
264 		{
265 			.prefixes = (const struct test_log_event []) {
266 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
267 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
268 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
269 				{ .type = TYPE_END }
270 			},
271 			.global_log_prefix = "global4.",
272 			.result = "global4.Info: "
273 				"appended1-[amended1-appended2-TEXT]",
274 		},
275 		{
276 			.prefixes = (const struct test_log_event []) {
277 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
278 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
279 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
280 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
281 				{ .type = TYPE_END }
282 			},
283 			.global_log_prefix = "global4.",
284 			.result = "global4.Info: [amended1-appended1-"
285 				"[amended2-appended2-TEXT]]",
286 		},
287 		{
288 			.prefixes = (const struct test_log_event []) {
289 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
290 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
291 				{ .type = TYPE_END }
292 			},
293 			.result = "replaced1,Info: [amended1-TEXT]",
294 		},
295 		{
296 			.prefixes = (const struct test_log_event []) {
297 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
298 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
299 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
300 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
301 				{ .type = TYPE_END }
302 			},
303 			.result = "replaced2,Info: [amended2-TEXT]",
304 		},
305 		/* Tests with params->base_str_out != NULL */
306 		{
307 			.prefixes = (const struct test_log_event []) {
308 				{ .type = TYPE_END }
309 			},
310 			.global_log_prefix = "global1.",
311 			.result = "global1.Info: TEXT",
312 			.result_str_out = "TEXT",
313 		},
314 		{
315 			.prefixes = (const struct test_log_event []) {
316 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
317 				{ .type = TYPE_END }
318 			},
319 			.result = "replaced1,Info: TEXT",
320 			.result_str_out = "TEXT",
321 		},
322 		{
323 			.prefixes = (const struct test_log_event []) {
324 				{ TYPE_PREFIX_REPLACE, "replaced1,",
325 				  FLAG_BASE_EVENT },
326 				{ .type = TYPE_END }
327 			},
328 			.result = "replaced1,Info: TEXT",
329 			.result_str_out = "TEXT",
330 		},
331 		{
332 			.prefixes = (const struct test_log_event []) {
333 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
334 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
335 				{ .type = TYPE_END }
336 			},
337 			.result = "replaced2.Info: TEXT",
338 			.result_str_out = "TEXT",
339 		},
340 		{
341 			.prefixes = (const struct test_log_event []) {
342 				{ TYPE_PREFIX_REPLACE, "replaced1,",
343 				  FLAG_BASE_EVENT },
344 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
345 				{ .type = TYPE_END }
346 			},
347 			.result = "replaced2.Info: TEXT",
348 			.result_str_out = "TEXT",
349 		},
350 		{
351 			.prefixes = (const struct test_log_event []) {
352 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
353 				{ TYPE_PREFIX_REPLACE, "replaced2.",
354 				  FLAG_BASE_EVENT },
355 				{ .type = TYPE_END }
356 			},
357 			.result = "replaced2.Info: TEXT",
358 			.result_str_out = "TEXT",
359 		},
360 		{
361 			.prefixes = (const struct test_log_event []) {
362 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
363 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
364 				{ .type = TYPE_END }
365 			},
366 			.result = "replaced1,Info: appended2.TEXT",
367 			.result_str_out = "appended2.TEXT",
368 		},
369 		{
370 			.prefixes = (const struct test_log_event []) {
371 				{ TYPE_PREFIX_REPLACE, "replaced1,",
372 				  FLAG_BASE_EVENT },
373 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
374 				{ .type = TYPE_END }
375 			},
376 			.result = "replaced1,Info: appended2.TEXT",
377 			.result_str_out = "appended2.TEXT",
378 		},
379 		{
380 			.prefixes = (const struct test_log_event []) {
381 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
382 				{ TYPE_PREFIX_APPEND, "appended2.",
383 				  FLAG_BASE_EVENT },
384 				{ .type = TYPE_END }
385 			},
386 			.result = "replaced1,Info: appended2.TEXT",
387 			.result_str_out = "TEXT",
388 		},
389 		{
390 			.prefixes = (const struct test_log_event []) {
391 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
392 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
393 				{ .type = TYPE_END }
394 			},
395 			.result = "replaced1,Info: TEXT",
396 			.result_str_out = "TEXT",
397 		},
398 		{
399 			.prefixes = (const struct test_log_event []) {
400 				{ TYPE_PREFIX_APPEND, "appended1,",
401 				  FLAG_BASE_EVENT },
402 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
403 				{ .type = TYPE_END }
404 			},
405 			.result = "replaced1,Info: TEXT",
406 			.result_str_out = "TEXT",
407 		},
408 		{
409 			.prefixes = (const struct test_log_event []) {
410 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
411 				{ TYPE_PREFIX_REPLACE, "replaced1,",
412 				  FLAG_BASE_EVENT },
413 				{ .type = TYPE_END }
414 			},
415 			.result = "replaced1,Info: TEXT",
416 			.result_str_out = "TEXT",
417 		},
418 		{
419 			.prefixes = (const struct test_log_event []) {
420 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
421 				{ .type = TYPE_END }
422 			},
423 			.global_log_prefix = "global2.",
424 			.result = "global2.Info: appended1,TEXT",
425 			.result_str_out = "appended1,TEXT",
426 		},
427 		{
428 			.prefixes = (const struct test_log_event []) {
429 				{ TYPE_PREFIX_APPEND, "appended1,",
430 				  FLAG_BASE_EVENT },
431 				{ .type = TYPE_END }
432 			},
433 			.global_log_prefix = "global2.",
434 			.result = "global2.Info: appended1,TEXT",
435 			.result_str_out = "TEXT",
436 		},
437 		{
438 			.prefixes = (const struct test_log_event []) {
439 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
440 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
441 				{ .type = TYPE_END }
442 			},
443 			.global_log_prefix = "global3.",
444 			.result = "global3.Info: appended1,appended2.TEXT",
445 			.result_str_out = "appended1,appended2.TEXT",
446 		},
447 		{
448 			.prefixes = (const struct test_log_event []) {
449 				{ TYPE_PREFIX_APPEND, "appended1,",
450 				  FLAG_BASE_EVENT },
451 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
452 				{ .type = TYPE_END }
453 			},
454 			.global_log_prefix = "global3.",
455 			.result = "global3.Info: appended1,appended2.TEXT",
456 			.result_str_out = "appended2.TEXT",
457 		},
458 		{
459 			.prefixes = (const struct test_log_event []) {
460 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
461 				{ TYPE_PREFIX_APPEND, "appended2.",
462 				  FLAG_BASE_EVENT },
463 				{ .type = TYPE_END }
464 			},
465 			.global_log_prefix = "global3.",
466 			.result = "global3.Info: appended1,appended2.TEXT",
467 			.result_str_out = "TEXT",
468 		},
469 		{
470 			.prefixes = (const struct test_log_event []) {
471 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
472 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
473 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
474 				{ .type = TYPE_END }
475 			},
476 			.global_log_prefix = "global3.",
477 			.result = "global3.Info: "
478 				  "appended1,appended2.appended3.TEXT",
479 			.result_str_out = "appended1,appended2.appended3.TEXT",
480 		},
481 		{
482 			.prefixes = (const struct test_log_event []) {
483 				{ TYPE_PREFIX_APPEND, "appended1,",
484 				  FLAG_BASE_EVENT },
485 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
486 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
487 				{ .type = TYPE_END }
488 			},
489 			.global_log_prefix = "global3.",
490 			.result = "global3.Info: "
491 				  "appended1,appended2.appended3.TEXT",
492 			.result_str_out = "appended2.appended3.TEXT",
493 		},
494 		{
495 			.prefixes = (const struct test_log_event []) {
496 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
497 				{ TYPE_PREFIX_APPEND, "appended2.",
498 				  FLAG_BASE_EVENT },
499 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
500 				{ .type = TYPE_END }
501 			},
502 			.global_log_prefix = "global3.",
503 			.result = "global3.Info: "
504 				  "appended1,appended2.appended3.TEXT",
505 			.result_str_out = "appended3.TEXT",
506 		},
507 		{
508 			.prefixes = (const struct test_log_event []) {
509 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
510 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
511 				{ TYPE_PREFIX_APPEND, "appended3.",
512 				  FLAG_BASE_EVENT },
513 				{ .type = TYPE_END }
514 			},
515 			.global_log_prefix = "global3.",
516 			.result = "global3.Info: "
517 				  "appended1,appended2.appended3.TEXT",
518 			.result_str_out = "TEXT",
519 		},
520 		{
521 			.prefixes = (const struct test_log_event []) {
522 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
523 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
524 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
525 				{ .type = TYPE_END }
526 			},
527 			.result = "replaced2.Info: appended3#TEXT",
528 			.result_str_out = "appended3#TEXT",
529 		},
530 		{
531 			.prefixes = (const struct test_log_event []) {
532 				{ TYPE_PREFIX_APPEND, "appended1,",
533 				  FLAG_BASE_EVENT },
534 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
535 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
536 				{ .type = TYPE_END }
537 			},
538 			.result = "replaced2.Info: appended3#TEXT",
539 			.result_str_out = "appended3#TEXT",
540 		},
541 		{
542 			.prefixes = (const struct test_log_event []) {
543 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
544 				{ TYPE_PREFIX_REPLACE, "replaced2.",
545 				  FLAG_BASE_EVENT },
546 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
547 				{ .type = TYPE_END }
548 			},
549 			.result = "replaced2.Info: appended3#TEXT",
550 			.result_str_out = "appended3#TEXT",
551 		},
552 		{
553 			.prefixes = (const struct test_log_event []) {
554 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
555 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
556 				{ TYPE_PREFIX_APPEND, "appended3#",
557 				  FLAG_BASE_EVENT },
558 				{ .type = TYPE_END }
559 			},
560 			.result = "replaced2.Info: appended3#TEXT",
561 			.result_str_out = "TEXT",
562 		},
563 		{
564 			.prefixes = (const struct test_log_event []) {
565 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
566 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
567 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
568 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
569 				{ .type = TYPE_END }
570 			},
571 			.result = "replaced4;Info: TEXT",
572 			.result_str_out = "TEXT",
573 		},
574 		{
575 			.prefixes = (const struct test_log_event []) {
576 				{ TYPE_PREFIX_APPEND, "appended1,",
577 				  FLAG_BASE_EVENT },
578 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
579 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
580 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
581 				{ .type = TYPE_END }
582 			},
583 			.result = "replaced4;Info: TEXT",
584 			.result_str_out = "TEXT",
585 		},
586 		{
587 			.prefixes = (const struct test_log_event []) {
588 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
589 				{ TYPE_PREFIX_REPLACE, "replaced2.",
590 				  FLAG_BASE_EVENT },
591 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
592 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
593 				{ .type = TYPE_END }
594 			},
595 			.result = "replaced4;Info: TEXT",
596 			.result_str_out = "TEXT",
597 		},
598 		{
599 			.prefixes = (const struct test_log_event []) {
600 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
601 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
602 				{ TYPE_PREFIX_APPEND, "appended3#",
603 				  FLAG_BASE_EVENT },
604 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
605 				{ .type = TYPE_END }
606 			},
607 			.result = "replaced4;Info: TEXT",
608 			.result_str_out = "TEXT",
609 		},
610 		{
611 			.prefixes = (const struct test_log_event []) {
612 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
613 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
614 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
615 				{ TYPE_PREFIX_REPLACE, "replaced4;",
616 				  FLAG_BASE_EVENT },
617 				{ .type = TYPE_END }
618 			},
619 			.result = "replaced4;Info: TEXT",
620 			.result_str_out = "TEXT",
621 		},
622 		{
623 			.prefixes = (const struct test_log_event []) {
624 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
625 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
626 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
627 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
628 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
629 				{ .type = TYPE_END }
630 			},
631 			.result = "replaced4;Info: appended5-TEXT",
632 			.result_str_out = "appended5-TEXT",
633 		},
634 		{
635 			.prefixes = (const struct test_log_event []) {
636 				{ TYPE_PREFIX_APPEND, "appended1,",
637 				  FLAG_BASE_EVENT },
638 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
639 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
640 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
641 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
642 				{ .type = TYPE_END }
643 			},
644 			.result = "replaced4;Info: appended5-TEXT",
645 			.result_str_out = "appended5-TEXT",
646 		},
647 		{
648 			.prefixes = (const struct test_log_event []) {
649 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
650 				{ TYPE_PREFIX_REPLACE, "replaced2.",
651 				  FLAG_BASE_EVENT },
652 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
653 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
654 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
655 				{ .type = TYPE_END }
656 			},
657 			.result = "replaced4;Info: appended5-TEXT",
658 			.result_str_out = "appended5-TEXT",
659 		},
660 		{
661 			.prefixes = (const struct test_log_event []) {
662 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
663 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
664 				{ TYPE_PREFIX_APPEND, "appended3#",
665 				  FLAG_BASE_EVENT },
666 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
667 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
668 				{ .type = TYPE_END }
669 			},
670 			.result = "replaced4;Info: appended5-TEXT",
671 			.result_str_out = "appended5-TEXT",
672 		},
673 		{
674 			.prefixes = (const struct test_log_event []) {
675 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
676 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
677 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
678 				{ TYPE_PREFIX_REPLACE, "replaced4;",
679 				  FLAG_BASE_EVENT },
680 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
681 				{ .type = TYPE_END }
682 			},
683 			.result = "replaced4;Info: appended5-TEXT",
684 			.result_str_out = "appended5-TEXT",
685 		},
686 		{
687 			.prefixes = (const struct test_log_event []) {
688 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
689 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
690 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
691 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
692 				{ TYPE_PREFIX_APPEND, "appended5-",
693 				  FLAG_BASE_EVENT },
694 				{ .type = TYPE_END }
695 			},
696 			.result = "replaced4;Info: appended5-TEXT",
697 			.result_str_out = "TEXT",
698 		},
699 		{
700 			.prefixes = (const struct test_log_event []) {
701 				{ TYPE_PREFIX_APPEND_CB, "appended1-", 0 },
702 				{ .type = TYPE_END }
703 			},
704 			.global_log_prefix = "global3.",
705 			.result = "global3.Info: callback(appended1-)TEXT",
706 			.result_str_out = "callback(appended1-)TEXT",
707 		},
708 		{
709 			.prefixes = (const struct test_log_event []) {
710 				{ TYPE_PREFIX_APPEND_CB, "appended1-",
711 				  FLAG_BASE_EVENT },
712 				{ .type = TYPE_END }
713 			},
714 			.global_log_prefix = "global3.",
715 			.result = "global3.Info: callback(appended1-)TEXT",
716 			.result_str_out = "TEXT",
717 		},
718 		{
719 			.prefixes = (const struct test_log_event []) {
720 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
721 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
722 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
723 				{ .type = TYPE_END }
724 			},
725 			.result = "callback(replaced2-)Info: TEXT",
726 			.result_str_out = "TEXT",
727 		},
728 		{
729 			.prefixes = (const struct test_log_event []) {
730 				{ TYPE_PREFIX_APPEND, "appended1,",
731 				  FLAG_BASE_EVENT },
732 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
733 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
734 				{ .type = TYPE_END }
735 			},
736 			.result = "callback(replaced2-)Info: TEXT",
737 			.result_str_out = "TEXT",
738 		},
739 		{
740 			.prefixes = (const struct test_log_event []) {
741 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
742 				{ TYPE_PREFIX_REPLACE, "replaced1.",
743 				  FLAG_BASE_EVENT },
744 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
745 				{ .type = TYPE_END }
746 			},
747 			.result = "callback(replaced2-)Info: TEXT",
748 			.result_str_out = "TEXT",
749 		},
750 		{
751 			.prefixes = (const struct test_log_event []) {
752 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
753 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
754 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-",
755 				  FLAG_BASE_EVENT },
756 				{ .type = TYPE_END }
757 			},
758 			.result = "callback(replaced2-)Info: TEXT",
759 			.result_str_out = "TEXT",
760 		},
761 		{
762 			.prefixes = (const struct test_log_event []) {
763 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
764 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
765 				{ .type = TYPE_END }
766 			},
767 			.result = "callback(replaced1.)Info: appended1,TEXT",
768 			.result_str_out = "appended1,TEXT",
769 		},
770 		{
771 			.prefixes = (const struct test_log_event []) {
772 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.",
773 				  FLAG_BASE_EVENT },
774 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
775 				{ .type = TYPE_END }
776 			},
777 			.result = "callback(replaced1.)Info: appended1,TEXT",
778 			.result_str_out = "appended1,TEXT",
779 		},
780 		{
781 			.prefixes = (const struct test_log_event []) {
782 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
783 				{ TYPE_PREFIX_APPEND, "appended1,",
784 				  FLAG_BASE_EVENT },
785 				{ .type = TYPE_END }
786 			},
787 			.result = "callback(replaced1.)Info: appended1,TEXT",
788 			.result_str_out = "TEXT",
789 		},
790 		{
791 			.prefixes = (const struct test_log_event []) {
792 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
793 				{ TYPE_PREFIX_REPLACE, "replaced2-", 0 },
794 				{ .type = TYPE_END }
795 			},
796 			.result = "replaced2-Info: TEXT",
797 			.result_str_out = "TEXT",
798 		},
799 		{
800 			.prefixes = (const struct test_log_event []) {
801 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.",
802 				  FLAG_BASE_EVENT },
803 				{ TYPE_PREFIX_REPLACE, "replaced2-", 0 },
804 				{ .type = TYPE_END }
805 			},
806 			.result = "replaced2-Info: TEXT",
807 			.result_str_out = "TEXT",
808 		},
809 		{
810 			.prefixes = (const struct test_log_event []) {
811 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
812 				{ TYPE_PREFIX_REPLACE, "replaced2-",
813 				  FLAG_BASE_EVENT },
814 				{ .type = TYPE_END }
815 			},
816 			.result = "replaced2-Info: TEXT",
817 			.result_str_out = "TEXT",
818 		},
819 		{
820 			.prefixes = (const struct test_log_event []) {
821 				{ TYPE_MESSAGE_AMEND, "amended1-" , 0},
822 				{ .type = TYPE_END }
823 			},
824 			.global_log_prefix = "global4.",
825 			.result = "global4.Info: [amended1-TEXT]",
826 			.result_str_out = "[amended1-TEXT]",
827 		},
828 		{
829 			.prefixes = (const struct test_log_event []) {
830 				{ TYPE_MESSAGE_AMEND, "amended1-" ,
831 				  FLAG_BASE_EVENT},
832 				{ .type = TYPE_END }
833 			},
834 			.global_log_prefix = "global4.",
835 			.result = "global4.Info: [amended1-TEXT]",
836 			.result_str_out = "TEXT",
837 		},
838 		{
839 			.prefixes = (const struct test_log_event []) {
840 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
841 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
842 				{ .type = TYPE_END }
843 			},
844 			.global_log_prefix = "global4.",
845 			.result = "global4.Info: [amended1-[amended2-TEXT]]",
846 			.result_str_out = "[amended1-[amended2-TEXT]]",
847 		},
848 		{
849 			.prefixes = (const struct test_log_event []) {
850 				{ TYPE_MESSAGE_AMEND, "amended1-",
851 				  FLAG_BASE_EVENT },
852 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
853 				{ .type = TYPE_END }
854 			},
855 			.global_log_prefix = "global4.",
856 			.result = "global4.Info: [amended1-[amended2-TEXT]]",
857 			.result_str_out = "[amended2-TEXT]",
858 		},
859 		{
860 			.prefixes = (const struct test_log_event []) {
861 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
862 				{ TYPE_MESSAGE_AMEND, "amended2-",
863 				  FLAG_BASE_EVENT },
864 				{ .type = TYPE_END }
865 			},
866 			.global_log_prefix = "global4.",
867 			.result = "global4.Info: [amended1-[amended2-TEXT]]",
868 			.result_str_out = "TEXT",
869 		},
870 		{
871 			.prefixes = (const struct test_log_event []) {
872 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
873 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
874 				{ .type = TYPE_END }
875 			},
876 			.global_log_prefix = "global4.",
877 			.result = "global4.Info: [amended1-appended1-TEXT]",
878 			.result_str_out = "[amended1-appended1-TEXT]",
879 		},
880 		{
881 			.prefixes = (const struct test_log_event []) {
882 				{ TYPE_MESSAGE_AMEND, "amended1-",
883 				  FLAG_BASE_EVENT },
884 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
885 				{ .type = TYPE_END }
886 			},
887 			.global_log_prefix = "global4.",
888 			.result = "global4.Info: [amended1-appended1-TEXT]",
889 			.result_str_out = "appended1-TEXT",
890 		},
891 		{
892 			.prefixes = (const struct test_log_event []) {
893 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
894 				{ TYPE_PREFIX_APPEND, "appended1-",
895 				  FLAG_BASE_EVENT },
896 				{ .type = TYPE_END }
897 			},
898 			.global_log_prefix = "global4.",
899 			.result = "global4.Info: [amended1-appended1-TEXT]",
900 			.result_str_out = "TEXT",
901 		},
902 		{
903 			.prefixes = (const struct test_log_event []) {
904 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
905 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
906 				{ .type = TYPE_END }
907 			},
908 			.global_log_prefix = "global4.",
909 			.result = "global4.Info: appended1-[amended1-TEXT]",
910 			.result_str_out = "appended1-[amended1-TEXT]",
911 		},
912 		{
913 			.prefixes = (const struct test_log_event []) {
914 				{ TYPE_PREFIX_APPEND, "appended1-",
915 				  FLAG_BASE_EVENT },
916 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
917 				{ .type = TYPE_END }
918 			},
919 			.global_log_prefix = "global4.",
920 			.result = "global4.Info: appended1-[amended1-TEXT]",
921 			.result_str_out = "[amended1-TEXT]",
922 		},
923 		{
924 			.prefixes = (const struct test_log_event []) {
925 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
926 				{ TYPE_MESSAGE_AMEND, "amended1-",
927 				  FLAG_BASE_EVENT },
928 				{ .type = TYPE_END }
929 			},
930 			.global_log_prefix = "global4.",
931 			.result = "global4.Info: appended1-[amended1-TEXT]",
932 			.result_str_out = "TEXT",
933 		},
934 		{
935 			.prefixes = (const struct test_log_event []) {
936 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
937 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
938 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
939 				{ .type = TYPE_END }
940 			},
941 			.global_log_prefix = "global4.",
942 			.result = "global4.Info: "
943 				"appended1-[amended1-appended2-TEXT]",
944 			.result_str_out = "appended1-[amended1-appended2-TEXT]",
945 		},
946 		{
947 			.prefixes = (const struct test_log_event []) {
948 				{ TYPE_PREFIX_APPEND, "appended1-",
949 				  FLAG_BASE_EVENT },
950 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
951 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
952 				{ .type = TYPE_END }
953 			},
954 			.global_log_prefix = "global4.",
955 			.result = "global4.Info: "
956 				"appended1-[amended1-appended2-TEXT]",
957 			.result_str_out = "[amended1-appended2-TEXT]",
958 		},
959 		{
960 			.prefixes = (const struct test_log_event []) {
961 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
962 				{ TYPE_MESSAGE_AMEND, "amended1-",
963 				  FLAG_BASE_EVENT },
964 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
965 				{ .type = TYPE_END }
966 			},
967 			.global_log_prefix = "global4.",
968 			.result = "global4.Info: "
969 				"appended1-[amended1-appended2-TEXT]",
970 			.result_str_out = "appended2-TEXT",
971 		},
972 		{
973 			.prefixes = (const struct test_log_event []) {
974 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
975 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
976 				{ TYPE_PREFIX_APPEND, "appended2-",
977 				  FLAG_BASE_EVENT },
978 				{ .type = TYPE_END }
979 			},
980 			.global_log_prefix = "global4.",
981 			.result = "global4.Info: "
982 				"appended1-[amended1-appended2-TEXT]",
983 			.result_str_out = "TEXT",
984 		},
985 		{
986 			.prefixes = (const struct test_log_event []) {
987 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
988 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
989 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
990 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
991 				{ .type = TYPE_END }
992 			},
993 			.global_log_prefix = "global4.",
994 			.result = "global4.Info: [amended1-appended1-"
995 				"[amended2-appended2-TEXT]]",
996 			.result_str_out = "[amended1-appended1-"
997 				"[amended2-appended2-TEXT]]",
998 		},
999 		{
1000 			.prefixes = (const struct test_log_event []) {
1001 				{ TYPE_MESSAGE_AMEND, "amended1-",
1002 				  FLAG_BASE_EVENT },
1003 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1004 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1005 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1006 				{ .type = TYPE_END }
1007 			},
1008 			.global_log_prefix = "global4.",
1009 			.result = "global4.Info: [amended1-appended1-"
1010 				"[amended2-appended2-TEXT]]",
1011 			.result_str_out = "appended1-[amended2-appended2-TEXT]",
1012 		},
1013 		{
1014 			.prefixes = (const struct test_log_event []) {
1015 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1016 				{ TYPE_PREFIX_APPEND, "appended1-",
1017 				  FLAG_BASE_EVENT },
1018 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1019 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1020 				{ .type = TYPE_END }
1021 			},
1022 			.global_log_prefix = "global4.",
1023 			.result = "global4.Info: [amended1-appended1-"
1024 				"[amended2-appended2-TEXT]]",
1025 			.result_str_out = "[amended2-appended2-TEXT]",
1026 		},
1027 		{
1028 			.prefixes = (const struct test_log_event []) {
1029 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1030 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1031 				{ TYPE_MESSAGE_AMEND, "amended2-",
1032 				  FLAG_BASE_EVENT },
1033 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1034 				{ .type = TYPE_END }
1035 			},
1036 			.global_log_prefix = "global4.",
1037 			.result = "global4.Info: [amended1-appended1-"
1038 				"[amended2-appended2-TEXT]]",
1039 			.result_str_out = "appended2-TEXT",
1040 		},
1041 		{
1042 			.prefixes = (const struct test_log_event []) {
1043 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1044 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1045 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1046 				{ TYPE_PREFIX_APPEND, "appended2-",
1047 				  FLAG_BASE_EVENT },
1048 				{ .type = TYPE_END }
1049 			},
1050 			.global_log_prefix = "global4.",
1051 			.result = "global4.Info: [amended1-appended1-"
1052 				"[amended2-appended2-TEXT]]",
1053 			.result_str_out = "TEXT",
1054 		},
1055 		{
1056 			.prefixes = (const struct test_log_event []) {
1057 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1058 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1059 				{ .type = TYPE_END }
1060 			},
1061 			.result = "replaced1,Info: [amended1-TEXT]",
1062 			.result_str_out = "[amended1-TEXT]",
1063 		},
1064 		{
1065 			.prefixes = (const struct test_log_event []) {
1066 				{ TYPE_PREFIX_REPLACE, "replaced1,",
1067 				  FLAG_BASE_EVENT },
1068 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1069 				{ .type = TYPE_END }
1070 			},
1071 			.result = "replaced1,Info: [amended1-TEXT]",
1072 			.result_str_out = "[amended1-TEXT]",
1073 		},
1074 		{
1075 			.prefixes = (const struct test_log_event []) {
1076 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1077 				{ TYPE_MESSAGE_AMEND, "amended1-",
1078 				  FLAG_BASE_EVENT },
1079 				{ .type = TYPE_END }
1080 			},
1081 			.result = "replaced1,Info: [amended1-TEXT]",
1082 			.result_str_out = "TEXT",
1083 		},
1084 		{
1085 			.prefixes = (const struct test_log_event []) {
1086 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1087 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1088 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
1089 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1090 				{ .type = TYPE_END }
1091 			},
1092 			.result = "replaced2,Info: [amended2-TEXT]",
1093 			.result_str_out = "[amended2-TEXT]",
1094 		},
1095 		{
1096 			.prefixes = (const struct test_log_event []) {
1097 				{ TYPE_PREFIX_REPLACE, "replaced1,",
1098 				  FLAG_BASE_EVENT },
1099 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1100 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
1101 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1102 				{ .type = TYPE_END }
1103 			},
1104 			.result = "replaced2,Info: [amended2-TEXT]",
1105 			.result_str_out = "[amended2-TEXT]",
1106 		},
1107 		{
1108 			.prefixes = (const struct test_log_event []) {
1109 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1110 				{ TYPE_MESSAGE_AMEND, "amended1-",
1111 				  FLAG_BASE_EVENT },
1112 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
1113 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1114 				{ .type = TYPE_END }
1115 			},
1116 			.result = "replaced2,Info: [amended2-TEXT]",
1117 			.result_str_out = "[amended2-TEXT]",
1118 		},
1119 		{
1120 			.prefixes = (const struct test_log_event []) {
1121 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1122 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1123 				{ TYPE_PREFIX_REPLACE, "replaced2,",
1124 				  FLAG_BASE_EVENT },
1125 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1126 				{ .type = TYPE_END }
1127 			},
1128 			.result = "replaced2,Info: [amended2-TEXT]",
1129 			.result_str_out = "[amended2-TEXT]",
1130 		},
1131 		{
1132 			.prefixes = (const struct test_log_event []) {
1133 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1134 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1135 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
1136 				{ TYPE_MESSAGE_AMEND, "amended2-",
1137 				  FLAG_BASE_EVENT },
1138 				{ .type = TYPE_END }
1139 			},
1140 			.result = "replaced2,Info: [amended2-TEXT]",
1141 			.result_str_out = "TEXT",
1142 		},
1143 		/* Tests involving params->no_send */
1144 		{
1145 			.prefixes = (const struct test_log_event []) {
1146 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1147 				{ TYPE_PREFIX_APPEND, "appended2.",
1148 				  FLAG_BASE_EVENT },
1149 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
1150 				{ .type = TYPE_END }
1151 			},
1152 			.global_log_prefix = "global3.",
1153 			.result = NULL,
1154 			.result_str_out = "appended3.TEXT",
1155 			.flags = FLAG_NO_SEND,
1156 		},
1157 		{
1158 			.prefixes = (const struct test_log_event []) {
1159 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1160 				{ TYPE_PREFIX_APPEND, "appended1-",
1161 				  FLAG_BASE_EVENT },
1162 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1163 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1164 				{ .type = TYPE_END }
1165 			},
1166 			.global_log_prefix = "global4.",
1167 			.result = NULL,
1168 			.result_str_out = "[amended2-appended2-TEXT]",
1169 			.flags = FLAG_NO_SEND,
1170 		},
1171 		/* Tests with params->base_*_prefix assigned */
1172 		{
1173 			.prefixes = (const struct test_log_event []) {
1174 				{ .type = TYPE_END }
1175 			},
1176 			.global_log_prefix = "global1.",
1177 			.base_send_prefix = "PREFIX: ",
1178 			.base_str_prefix = "STR_PREFIX: ",
1179 			.result = "global1.Info: PREFIX: TEXT",
1180 			.result_str_out = "STR_PREFIX: TEXT",
1181 		},
1182 		{
1183 			.prefixes = (const struct test_log_event []) {
1184 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1185 				{ .type = TYPE_END }
1186 			},
1187 			.base_send_prefix = "PREFIX: ",
1188 			.base_str_prefix = "STR_PREFIX: ",
1189 
1190 			.result = "replaced1,Info: TEXT",
1191 			.result_str_out = "TEXT",
1192 		},
1193 		{
1194 			.prefixes = (const struct test_log_event []) {
1195 				{ TYPE_PREFIX_REPLACE, "replaced1,",
1196 				  FLAG_BASE_EVENT },
1197 				{ .type = TYPE_END }
1198 			},
1199 			.base_send_prefix = "PREFIX: ",
1200 			.base_str_prefix = "STR_PREFIX: ",
1201 			.result = "replaced1,Info: PREFIX: TEXT",
1202 			.result_str_out = "STR_PREFIX: TEXT",
1203 		},
1204 		{
1205 			.prefixes = (const struct test_log_event []) {
1206 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1207 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1208 				{ .type = TYPE_END }
1209 			},
1210 			.base_send_prefix = "PREFIX: ",
1211 			.base_str_prefix = "STR_PREFIX: ",
1212 			.result = "replaced2.Info: TEXT",
1213 			.result_str_out = "TEXT",
1214 		},
1215 		{
1216 			.prefixes = (const struct test_log_event []) {
1217 				{ TYPE_PREFIX_REPLACE, "replaced1,",
1218 				  FLAG_BASE_EVENT },
1219 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1220 				{ .type = TYPE_END }
1221 			},
1222 			.base_send_prefix = "PREFIX: ",
1223 			.base_str_prefix = "STR_PREFIX: ",
1224 			.result = "replaced2.Info: TEXT",
1225 			.result_str_out = "TEXT",
1226 		},
1227 		{
1228 			.prefixes = (const struct test_log_event []) {
1229 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1230 				{ TYPE_PREFIX_REPLACE, "replaced2.",
1231 				  FLAG_BASE_EVENT },
1232 				{ .type = TYPE_END }
1233 			},
1234 			.base_send_prefix = "PREFIX: ",
1235 			.base_str_prefix = "STR_PREFIX: ",
1236 			.result = "replaced2.Info: PREFIX: TEXT",
1237 			.result_str_out = "STR_PREFIX: TEXT",
1238 		},
1239 		{
1240 			.prefixes = (const struct test_log_event []) {
1241 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1242 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1243 				{ .type = TYPE_END }
1244 			},
1245 			.base_send_prefix = "PREFIX: ",
1246 			.base_str_prefix = "STR_PREFIX: ",
1247 			.result = "replaced1,Info: appended2.TEXT",
1248 			.result_str_out = "appended2.TEXT",
1249 		},
1250 		{
1251 			.prefixes = (const struct test_log_event []) {
1252 				{ TYPE_PREFIX_REPLACE, "replaced1,",
1253 				  FLAG_BASE_EVENT },
1254 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1255 				{ .type = TYPE_END }
1256 			},
1257 			.base_send_prefix = "PREFIX: ",
1258 			.base_str_prefix = "STR_PREFIX: ",
1259 			.result = "replaced1,Info: PREFIX: appended2.TEXT",
1260 			.result_str_out = "STR_PREFIX: appended2.TEXT",
1261 		},
1262 		{
1263 			.prefixes = (const struct test_log_event []) {
1264 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1265 				{ TYPE_PREFIX_APPEND, "appended2.",
1266 				  FLAG_BASE_EVENT },
1267 				{ .type = TYPE_END }
1268 			},
1269 			.base_send_prefix = "PREFIX: ",
1270 			.base_str_prefix = "STR_PREFIX: ",
1271 			.result = "replaced1,Info: appended2.PREFIX: TEXT",
1272 			.result_str_out = "STR_PREFIX: TEXT",
1273 		},
1274 		{
1275 			.prefixes = (const struct test_log_event []) {
1276 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1277 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1278 				{ .type = TYPE_END }
1279 			},
1280 			.base_send_prefix = "PREFIX: ",
1281 			.base_str_prefix = "STR_PREFIX: ",
1282 			.result = "replaced1,Info: TEXT",
1283 			.result_str_out = "TEXT",
1284 		},
1285 		{
1286 			.prefixes = (const struct test_log_event []) {
1287 				{ TYPE_PREFIX_APPEND, "appended1,",
1288 				  FLAG_BASE_EVENT },
1289 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
1290 				{ .type = TYPE_END }
1291 			},
1292 			.base_send_prefix = "PREFIX: ",
1293 			.base_str_prefix = "STR_PREFIX: ",
1294 			.result = "replaced1,Info: TEXT",
1295 			.result_str_out = "TEXT",
1296 		},
1297 		{
1298 			.prefixes = (const struct test_log_event []) {
1299 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1300 				{ TYPE_PREFIX_REPLACE, "replaced1,",
1301 				  FLAG_BASE_EVENT },
1302 				{ .type = TYPE_END }
1303 			},
1304 			.base_send_prefix = "PREFIX: ",
1305 			.base_str_prefix = "STR_PREFIX: ",
1306 			.result = "replaced1,Info: PREFIX: TEXT",
1307 			.result_str_out = "STR_PREFIX: TEXT",
1308 		},
1309 		{
1310 			.prefixes = (const struct test_log_event []) {
1311 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1312 				{ .type = TYPE_END }
1313 			},
1314 			.global_log_prefix = "global2.",
1315 			.base_send_prefix = "PREFIX: ",
1316 			.base_str_prefix = "STR_PREFIX: ",
1317 			.result = "global2.Info: PREFIX: appended1,TEXT",
1318 			.result_str_out = "STR_PREFIX: appended1,TEXT",
1319 		},
1320 		{
1321 			.prefixes = (const struct test_log_event []) {
1322 				{ TYPE_PREFIX_APPEND, "appended1,",
1323 				  FLAG_BASE_EVENT },
1324 				{ .type = TYPE_END }
1325 			},
1326 			.global_log_prefix = "global2.",
1327 			.base_send_prefix = "PREFIX: ",
1328 			.base_str_prefix = "STR_PREFIX: ",
1329 			.result = "global2.Info: appended1,PREFIX: TEXT",
1330 			.result_str_out = "STR_PREFIX: TEXT",
1331 		},
1332 		{
1333 			.prefixes = (const struct test_log_event []) {
1334 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1335 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1336 				{ .type = TYPE_END }
1337 			},
1338 			.global_log_prefix = "global3.",
1339 			.base_send_prefix = "PREFIX: ",
1340 			.base_str_prefix = "STR_PREFIX: ",
1341 			.result = "global3.Info: PREFIX: "
1342 				"appended1,appended2.TEXT",
1343 			.result_str_out = "STR_PREFIX: "
1344 				"appended1,appended2.TEXT",
1345 		},
1346 		{
1347 			.prefixes = (const struct test_log_event []) {
1348 				{ TYPE_PREFIX_APPEND, "appended1,",
1349 				  FLAG_BASE_EVENT },
1350 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1351 				{ .type = TYPE_END }
1352 			},
1353 			.global_log_prefix = "global3.",
1354 			.base_send_prefix = "PREFIX: ",
1355 			.base_str_prefix = "STR_PREFIX: ",
1356 			.result = "global3.Info: appended1,PREFIX: "
1357 				"appended2.TEXT",
1358 			.result_str_out = "STR_PREFIX: appended2.TEXT",
1359 		},
1360 		{
1361 			.prefixes = (const struct test_log_event []) {
1362 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1363 				{ TYPE_PREFIX_APPEND, "appended2.",
1364 				  FLAG_BASE_EVENT },
1365 				{ .type = TYPE_END }
1366 			},
1367 			.global_log_prefix = "global3.",
1368 			.base_send_prefix = "PREFIX: ",
1369 			.base_str_prefix = "STR_PREFIX: ",
1370 			.result = "global3.Info: appended1,appended2."
1371 				"PREFIX: TEXT",
1372 			.result_str_out = "STR_PREFIX: TEXT",
1373 		},
1374 		{
1375 			.prefixes = (const struct test_log_event []) {
1376 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1377 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1378 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
1379 				{ .type = TYPE_END }
1380 			},
1381 			.global_log_prefix = "global3.",
1382 			.base_send_prefix = "PREFIX: ",
1383 			.base_str_prefix = "STR_PREFIX: ",
1384 			.result = "global3.Info: PREFIX: "
1385 				"appended1,appended2.appended3.TEXT",
1386 			.result_str_out = "STR_PREFIX: "
1387 				"appended1,appended2.appended3.TEXT",
1388 		},
1389 		{
1390 			.prefixes = (const struct test_log_event []) {
1391 				{ TYPE_PREFIX_APPEND, "appended1,",
1392 				  FLAG_BASE_EVENT },
1393 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1394 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
1395 				{ .type = TYPE_END }
1396 			},
1397 			.global_log_prefix = "global3.",
1398 			.base_send_prefix = "PREFIX: ",
1399 			.base_str_prefix = "STR_PREFIX: ",
1400 			.result = "global3.Info: appended1,PREFIX: "
1401 				"appended2.appended3.TEXT",
1402 			.result_str_out = "STR_PREFIX: "
1403 				"appended2.appended3.TEXT",
1404 		},
1405 		{
1406 			.prefixes = (const struct test_log_event []) {
1407 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1408 				{ TYPE_PREFIX_APPEND, "appended2.",
1409 				  FLAG_BASE_EVENT },
1410 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
1411 				{ .type = TYPE_END }
1412 			},
1413 			.global_log_prefix = "global3.",
1414 			.base_send_prefix = "PREFIX: ",
1415 			.base_str_prefix = "STR_PREFIX: ",
1416 			.result = "global3.Info: appended1,appended2.PREFIX: "
1417 				"appended3.TEXT",
1418 			.result_str_out = "STR_PREFIX: appended3.TEXT",
1419 		},
1420 		{
1421 			.prefixes = (const struct test_log_event []) {
1422 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1423 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
1424 				{ TYPE_PREFIX_APPEND, "appended3.",
1425 				  FLAG_BASE_EVENT },
1426 				{ .type = TYPE_END }
1427 			},
1428 			.global_log_prefix = "global3.",
1429 			.base_send_prefix = "PREFIX: ",
1430 			.base_str_prefix = "STR_PREFIX: ",
1431 			.result = "global3.Info: "
1432 				"appended1,appended2.appended3.PREFIX: TEXT",
1433 			.result_str_out = "STR_PREFIX: TEXT",
1434 		},
1435 		{
1436 			.prefixes = (const struct test_log_event []) {
1437 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1438 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1439 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1440 				{ .type = TYPE_END }
1441 			},
1442 			.base_send_prefix = "PREFIX: ",
1443 			.base_str_prefix = "STR_PREFIX: ",
1444 			.result = "replaced2.Info: appended3#TEXT",
1445 			.result_str_out = "appended3#TEXT",
1446 		},
1447 		{
1448 			.prefixes = (const struct test_log_event []) {
1449 				{ TYPE_PREFIX_APPEND, "appended1,",
1450 				  FLAG_BASE_EVENT },
1451 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1452 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1453 				{ .type = TYPE_END }
1454 			},
1455 			.base_send_prefix = "PREFIX: ",
1456 			.base_str_prefix = "STR_PREFIX: ",
1457 			.result = "replaced2.Info: appended3#TEXT",
1458 			.result_str_out = "appended3#TEXT",
1459 		},
1460 		{
1461 			.prefixes = (const struct test_log_event []) {
1462 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1463 				{ TYPE_PREFIX_REPLACE, "replaced2.",
1464 				  FLAG_BASE_EVENT },
1465 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1466 				{ .type = TYPE_END }
1467 			},
1468 			.base_send_prefix = "PREFIX: ",
1469 			.base_str_prefix = "STR_PREFIX: ",
1470 			.result = "replaced2.Info: PREFIX: appended3#TEXT",
1471 			.result_str_out = "STR_PREFIX: appended3#TEXT",
1472 		},
1473 		{
1474 			.prefixes = (const struct test_log_event []) {
1475 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1476 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1477 				{ TYPE_PREFIX_APPEND, "appended3#",
1478 				  FLAG_BASE_EVENT },
1479 				{ .type = TYPE_END }
1480 			},
1481 			.base_send_prefix = "PREFIX: ",
1482 			.base_str_prefix = "STR_PREFIX: ",
1483 			.result = "replaced2.Info: appended3#PREFIX: TEXT",
1484 			.result_str_out = "STR_PREFIX: TEXT",
1485 		},
1486 		{
1487 			.prefixes = (const struct test_log_event []) {
1488 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1489 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1490 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1491 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1492 				{ .type = TYPE_END }
1493 			},
1494 			.base_send_prefix = "PREFIX: ",
1495 			.base_str_prefix = "STR_PREFIX: ",
1496 			.result = "replaced4;Info: TEXT",
1497 			.result_str_out = "TEXT",
1498 		},
1499 		{
1500 			.prefixes = (const struct test_log_event []) {
1501 				{ TYPE_PREFIX_APPEND, "appended1,",
1502 				  FLAG_BASE_EVENT },
1503 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1504 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1505 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1506 				{ .type = TYPE_END }
1507 			},
1508 			.base_send_prefix = "PREFIX: ",
1509 			.base_str_prefix = "STR_PREFIX: ",
1510 			.result = "replaced4;Info: TEXT",
1511 			.result_str_out = "TEXT",
1512 		},
1513 		{
1514 			.prefixes = (const struct test_log_event []) {
1515 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1516 				{ TYPE_PREFIX_REPLACE, "replaced2.",
1517 				  FLAG_BASE_EVENT },
1518 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1519 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1520 				{ .type = TYPE_END }
1521 			},
1522 			.base_send_prefix = "PREFIX: ",
1523 			.base_str_prefix = "STR_PREFIX: ",
1524 			.result = "replaced4;Info: TEXT",
1525 			.result_str_out = "TEXT",
1526 		},
1527 		{
1528 			.prefixes = (const struct test_log_event []) {
1529 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1530 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1531 				{ TYPE_PREFIX_APPEND, "appended3#",
1532 				  FLAG_BASE_EVENT },
1533 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1534 				{ .type = TYPE_END }
1535 			},
1536 			.base_send_prefix = "PREFIX: ",
1537 			.base_str_prefix = "STR_PREFIX: ",
1538 			.result = "replaced4;Info: TEXT",
1539 			.result_str_out = "TEXT",
1540 		},
1541 		{
1542 			.prefixes = (const struct test_log_event []) {
1543 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1544 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1545 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1546 				{ TYPE_PREFIX_REPLACE, "replaced4;",
1547 				  FLAG_BASE_EVENT },
1548 				{ .type = TYPE_END }
1549 			},
1550 			.base_send_prefix = "PREFIX: ",
1551 			.base_str_prefix = "STR_PREFIX: ",
1552 			.result = "replaced4;Info: PREFIX: TEXT",
1553 			.result_str_out = "STR_PREFIX: TEXT",
1554 		},
1555 		{
1556 			.prefixes = (const struct test_log_event []) {
1557 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1558 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1559 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1560 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1561 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
1562 				{ .type = TYPE_END }
1563 			},
1564 			.base_send_prefix = "PREFIX: ",
1565 			.base_str_prefix = "STR_PREFIX: ",
1566 			.result = "replaced4;Info: appended5-TEXT",
1567 			.result_str_out = "appended5-TEXT",
1568 		},
1569 		{
1570 			.prefixes = (const struct test_log_event []) {
1571 				{ TYPE_PREFIX_APPEND, "appended1,",
1572 				  FLAG_BASE_EVENT },
1573 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1574 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1575 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1576 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
1577 				{ .type = TYPE_END }
1578 			},
1579 			.base_send_prefix = "PREFIX: ",
1580 			.base_str_prefix = "STR_PREFIX: ",
1581 			.result = "replaced4;Info: appended5-TEXT",
1582 			.result_str_out = "appended5-TEXT",
1583 		},
1584 		{
1585 			.prefixes = (const struct test_log_event []) {
1586 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1587 				{ TYPE_PREFIX_REPLACE, "replaced2.",
1588 				  FLAG_BASE_EVENT },
1589 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1590 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1591 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
1592 				{ .type = TYPE_END }
1593 			},
1594 			.base_send_prefix = "PREFIX: ",
1595 			.base_str_prefix = "STR_PREFIX: ",
1596 			.result = "replaced4;Info: appended5-TEXT",
1597 			.result_str_out = "appended5-TEXT",
1598 		},
1599 		{
1600 			.prefixes = (const struct test_log_event []) {
1601 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1602 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1603 				{ TYPE_PREFIX_APPEND, "appended3#",
1604 				  FLAG_BASE_EVENT },
1605 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1606 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
1607 				{ .type = TYPE_END }
1608 			},
1609 			.base_send_prefix = "PREFIX: ",
1610 			.base_str_prefix = "STR_PREFIX: ",
1611 			.result = "replaced4;Info: appended5-TEXT",
1612 			.result_str_out = "appended5-TEXT",
1613 		},
1614 		{
1615 			.prefixes = (const struct test_log_event []) {
1616 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1617 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1618 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1619 				{ TYPE_PREFIX_REPLACE, "replaced4;",
1620 				  FLAG_BASE_EVENT },
1621 				{ TYPE_PREFIX_APPEND, "appended5-", 0 },
1622 				{ .type = TYPE_END }
1623 			},
1624 			.base_send_prefix = "PREFIX: ",
1625 			.base_str_prefix = "STR_PREFIX: ",
1626 			.result = "replaced4;Info: PREFIX: appended5-TEXT",
1627 			.result_str_out = "STR_PREFIX: appended5-TEXT",
1628 		},
1629 		{
1630 			.prefixes = (const struct test_log_event []) {
1631 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1632 				{ TYPE_PREFIX_REPLACE, "replaced2.", 0 },
1633 				{ TYPE_PREFIX_APPEND, "appended3#", 0 },
1634 				{ TYPE_PREFIX_REPLACE, "replaced4;", 0 },
1635 				{ TYPE_PREFIX_APPEND, "appended5-",
1636 				  FLAG_BASE_EVENT },
1637 				{ .type = TYPE_END }
1638 			},
1639 			.base_send_prefix = "PREFIX: ",
1640 			.base_str_prefix = "STR_PREFIX: ",
1641 			.result = "replaced4;Info: appended5-PREFIX: TEXT",
1642 			.result_str_out = "STR_PREFIX: TEXT",
1643 		},
1644 		{
1645 			.prefixes = (const struct test_log_event []) {
1646 				{ TYPE_PREFIX_APPEND_CB, "appended1-", 0 },
1647 				{ .type = TYPE_END }
1648 			},
1649 			.global_log_prefix = "global3.",
1650 			.base_send_prefix = "PREFIX: ",
1651 			.base_str_prefix = "STR_PREFIX: ",
1652 			.result = "global3.Info: PREFIX: "
1653 				"callback(appended1-)TEXT",
1654 			.result_str_out = "STR_PREFIX: "
1655 				"callback(appended1-)TEXT",
1656 		},
1657 		{
1658 			.prefixes = (const struct test_log_event []) {
1659 				{ TYPE_PREFIX_APPEND_CB, "appended1-",
1660 				  FLAG_BASE_EVENT },
1661 				{ .type = TYPE_END }
1662 			},
1663 			.global_log_prefix = "global3.",
1664 			.base_send_prefix = "PREFIX: ",
1665 			.base_str_prefix = "STR_PREFIX: ",
1666 			.result = "global3.Info: callback(appended1-)PREFIX: "
1667 				"TEXT",
1668 			.result_str_out = "STR_PREFIX: TEXT",
1669 		},
1670 		{
1671 			.prefixes = (const struct test_log_event []) {
1672 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1673 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
1674 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
1675 				{ .type = TYPE_END }
1676 			},
1677 			.base_send_prefix = "PREFIX: ",
1678 			.base_str_prefix = "STR_PREFIX: ",
1679 			.result = "callback(replaced2-)Info: TEXT",
1680 			.result_str_out = "TEXT",
1681 		},
1682 		{
1683 			.prefixes = (const struct test_log_event []) {
1684 				{ TYPE_PREFIX_APPEND, "appended1,",
1685 				  FLAG_BASE_EVENT },
1686 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
1687 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
1688 				{ .type = TYPE_END }
1689 			},
1690 			.base_send_prefix = "PREFIX: ",
1691 			.base_str_prefix = "STR_PREFIX: ",
1692 			.result = "callback(replaced2-)Info: TEXT",
1693 			.result_str_out = "TEXT",
1694 		},
1695 		{
1696 			.prefixes = (const struct test_log_event []) {
1697 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1698 				{ TYPE_PREFIX_REPLACE, "replaced1.",
1699 				  FLAG_BASE_EVENT },
1700 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-", 0 },
1701 				{ .type = TYPE_END }
1702 			},
1703 			.base_send_prefix = "PREFIX: ",
1704 			.base_str_prefix = "STR_PREFIX: ",
1705 			.result = "callback(replaced2-)Info: TEXT",
1706 			.result_str_out = "TEXT",
1707 		},
1708 		{
1709 			.prefixes = (const struct test_log_event []) {
1710 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1711 				{ TYPE_PREFIX_REPLACE, "replaced1.", 0 },
1712 				{ TYPE_PREFIX_REPLACE_CB, "replaced2-",
1713 				  FLAG_BASE_EVENT },
1714 				{ .type = TYPE_END }
1715 			},
1716 			.base_send_prefix = "PREFIX: ",
1717 			.base_str_prefix = "STR_PREFIX: ",
1718 			.result = "callback(replaced2-)Info: PREFIX: TEXT",
1719 			.result_str_out = "STR_PREFIX: TEXT",
1720 		},
1721 		{
1722 			.prefixes = (const struct test_log_event []) {
1723 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
1724 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1725 				{ .type = TYPE_END }
1726 			},
1727 			.base_send_prefix = "PREFIX: ",
1728 			.base_str_prefix = "STR_PREFIX: ",
1729 			.result = "callback(replaced1.)Info: appended1,TEXT",
1730 			.result_str_out = "appended1,TEXT",
1731 		},
1732 		{
1733 			.prefixes = (const struct test_log_event []) {
1734 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.",
1735 				  FLAG_BASE_EVENT },
1736 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
1737 				{ .type = TYPE_END }
1738 			},
1739 			.base_send_prefix = "PREFIX: ",
1740 			.base_str_prefix = "STR_PREFIX: ",
1741 			.result = "callback(replaced1.)Info: PREFIX: "
1742 				"appended1,TEXT",
1743 			.result_str_out = "STR_PREFIX: appended1,TEXT",
1744 		},
1745 		{
1746 			.prefixes = (const struct test_log_event []) {
1747 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
1748 				{ TYPE_PREFIX_APPEND, "appended1,",
1749 				  FLAG_BASE_EVENT },
1750 				{ .type = TYPE_END }
1751 			},
1752 			.base_send_prefix = "PREFIX: ",
1753 			.base_str_prefix = "STR_PREFIX: ",
1754 			.result = "callback(replaced1.)Info: appended1,PREFIX: "
1755 				"TEXT",
1756 			.result_str_out = "STR_PREFIX: TEXT",
1757 		},
1758 		{
1759 			.prefixes = (const struct test_log_event []) {
1760 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
1761 				{ TYPE_PREFIX_REPLACE, "replaced2-", 0 },
1762 				{ .type = TYPE_END }
1763 			},
1764 			.base_send_prefix = "PREFIX: ",
1765 			.base_str_prefix = "STR_PREFIX: ",
1766 			.result = "replaced2-Info: TEXT",
1767 			.result_str_out = "TEXT",
1768 		},
1769 		{
1770 			.prefixes = (const struct test_log_event []) {
1771 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.",
1772 				  FLAG_BASE_EVENT },
1773 				{ TYPE_PREFIX_REPLACE, "replaced2-", 0 },
1774 				{ .type = TYPE_END }
1775 			},
1776 			.base_send_prefix = "PREFIX: ",
1777 			.base_str_prefix = "STR_PREFIX: ",
1778 			.result = "replaced2-Info: TEXT",
1779 			.result_str_out = "TEXT",
1780 		},
1781 		{
1782 			.prefixes = (const struct test_log_event []) {
1783 				{ TYPE_PREFIX_REPLACE_CB, "replaced1.", 0 },
1784 				{ TYPE_PREFIX_REPLACE, "replaced2-",
1785 				  FLAG_BASE_EVENT },
1786 				{ .type = TYPE_END }
1787 			},
1788 			.base_send_prefix = "PREFIX: ",
1789 			.base_str_prefix = "STR_PREFIX: ",
1790 			.result = "replaced2-Info: PREFIX: TEXT",
1791 			.result_str_out = "STR_PREFIX: TEXT",
1792 		},
1793 		{
1794 			.prefixes = (const struct test_log_event []) {
1795 				{ TYPE_MESSAGE_AMEND, "amended1-" , 0},
1796 				{ .type = TYPE_END }
1797 			},
1798 			.global_log_prefix = "global4.",
1799 			.base_send_prefix = "PREFIX: ",
1800 			.base_str_prefix = "STR_PREFIX: ",
1801 			.result = "global4.Info: PREFIX: [amended1-TEXT]",
1802 			.result_str_out = "STR_PREFIX: [amended1-TEXT]",
1803 		},
1804 		{
1805 			.prefixes = (const struct test_log_event []) {
1806 				{ TYPE_MESSAGE_AMEND, "amended1-" ,
1807 				  FLAG_BASE_EVENT},
1808 				{ .type = TYPE_END }
1809 			},
1810 			.global_log_prefix = "global4.",
1811 			.base_send_prefix = "PREFIX: ",
1812 			.base_str_prefix = "STR_PREFIX: ",
1813 			.result = "global4.Info: [amended1-PREFIX: TEXT]",
1814 			.result_str_out = "STR_PREFIX: TEXT",
1815 		},
1816 		{
1817 			.prefixes = (const struct test_log_event []) {
1818 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1819 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1820 				{ .type = TYPE_END }
1821 			},
1822 			.global_log_prefix = "global4.",
1823 			.base_send_prefix = "PREFIX: ",
1824 			.base_str_prefix = "STR_PREFIX: ",
1825 			.result = "global4.Info: PREFIX: "
1826 				"[amended1-[amended2-TEXT]]",
1827 			.result_str_out = "STR_PREFIX: "
1828 				"[amended1-[amended2-TEXT]]",
1829 		},
1830 		{
1831 			.prefixes = (const struct test_log_event []) {
1832 				{ TYPE_MESSAGE_AMEND, "amended1-",
1833 				  FLAG_BASE_EVENT },
1834 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
1835 				{ .type = TYPE_END }
1836 			},
1837 			.global_log_prefix = "global4.",
1838 			.base_send_prefix = "PREFIX: ",
1839 			.base_str_prefix = "STR_PREFIX: ",
1840 			.result = "global4.Info: [amended1-PREFIX: "
1841 				"[amended2-TEXT]]",
1842 			.result_str_out = "STR_PREFIX: [amended2-TEXT]",
1843 		},
1844 		{
1845 			.prefixes = (const struct test_log_event []) {
1846 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1847 				{ TYPE_MESSAGE_AMEND, "amended2-",
1848 				  FLAG_BASE_EVENT },
1849 				{ .type = TYPE_END }
1850 			},
1851 			.global_log_prefix = "global4.",
1852 			.base_send_prefix = "PREFIX: ",
1853 			.base_str_prefix = "STR_PREFIX: ",
1854 			.result = "global4.Info: [amended1-[amended2-PREFIX: "
1855 				"TEXT]]",
1856 			.result_str_out = "STR_PREFIX: TEXT",
1857 		},
1858 		{
1859 			.prefixes = (const struct test_log_event []) {
1860 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1861 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1862 				{ .type = TYPE_END }
1863 			},
1864 			.global_log_prefix = "global4.",
1865 			.base_send_prefix = "PREFIX: ",
1866 			.base_str_prefix = "STR_PREFIX: ",
1867 			.result = "global4.Info: PREFIX: "
1868 				"[amended1-appended1-TEXT]",
1869 			.result_str_out = "STR_PREFIX: "
1870 				"[amended1-appended1-TEXT]",
1871 		},
1872 		{
1873 			.prefixes = (const struct test_log_event []) {
1874 				{ TYPE_MESSAGE_AMEND, "amended1-",
1875 				  FLAG_BASE_EVENT },
1876 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1877 				{ .type = TYPE_END }
1878 			},
1879 			.global_log_prefix = "global4.",
1880 			.base_send_prefix = "PREFIX: ",
1881 			.base_str_prefix = "STR_PREFIX: ",
1882 			.result = "global4.Info: [amended1-PREFIX: "
1883 				"appended1-TEXT]",
1884 			.result_str_out = "STR_PREFIX: appended1-TEXT",
1885 		},
1886 		{
1887 			.prefixes = (const struct test_log_event []) {
1888 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1889 				{ TYPE_PREFIX_APPEND, "appended1-",
1890 				  FLAG_BASE_EVENT },
1891 				{ .type = TYPE_END }
1892 			},
1893 			.global_log_prefix = "global4.",
1894 			.base_send_prefix = "PREFIX: ",
1895 			.base_str_prefix = "STR_PREFIX: ",
1896 			.result = "global4.Info: [amended1-appended1-PREFIX: "
1897 				"TEXT]",
1898 			.result_str_out = "STR_PREFIX: TEXT",
1899 		},
1900 		{
1901 			.prefixes = (const struct test_log_event []) {
1902 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1903 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1904 				{ .type = TYPE_END }
1905 			},
1906 			.global_log_prefix = "global4.",
1907 			.base_send_prefix = "PREFIX: ",
1908 			.base_str_prefix = "STR_PREFIX: ",
1909 			.result = "global4.Info: PREFIX: "
1910 				"appended1-[amended1-TEXT]",
1911 			.result_str_out = "STR_PREFIX: "
1912 				"appended1-[amended1-TEXT]",
1913 		},
1914 		{
1915 			.prefixes = (const struct test_log_event []) {
1916 				{ TYPE_PREFIX_APPEND, "appended1-",
1917 				  FLAG_BASE_EVENT },
1918 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1919 				{ .type = TYPE_END }
1920 			},
1921 			.global_log_prefix = "global4.",
1922 			.base_send_prefix = "PREFIX: ",
1923 			.base_str_prefix = "STR_PREFIX: ",
1924 			.result = "global4.Info: appended1-PREFIX: "
1925 				"[amended1-TEXT]",
1926 			.result_str_out = "STR_PREFIX: [amended1-TEXT]",
1927 		},
1928 		{
1929 			.prefixes = (const struct test_log_event []) {
1930 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1931 				{ TYPE_MESSAGE_AMEND, "amended1-",
1932 				  FLAG_BASE_EVENT },
1933 				{ .type = TYPE_END }
1934 			},
1935 			.global_log_prefix = "global4.",
1936 			.base_send_prefix = "PREFIX: ",
1937 			.base_str_prefix = "STR_PREFIX: ",
1938 			.result = "global4.Info: appended1-[amended1-PREFIX: "
1939 				"TEXT]",
1940 			.result_str_out = "STR_PREFIX: TEXT",
1941 		},
1942 		{
1943 			.prefixes = (const struct test_log_event []) {
1944 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1945 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1946 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1947 				{ .type = TYPE_END }
1948 			},
1949 			.global_log_prefix = "global4.",
1950 			.base_send_prefix = "PREFIX: ",
1951 			.base_str_prefix = "STR_PREFIX: ",
1952 			.result = "global4.Info: PREFIX: "
1953 				"appended1-[amended1-appended2-TEXT]",
1954 			.result_str_out = "STR_PREFIX: "
1955 				"appended1-[amended1-appended2-TEXT]",
1956 		},
1957 		{
1958 			.prefixes = (const struct test_log_event []) {
1959 				{ TYPE_PREFIX_APPEND, "appended1-",
1960 				  FLAG_BASE_EVENT },
1961 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1962 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1963 				{ .type = TYPE_END }
1964 			},
1965 			.global_log_prefix = "global4.",
1966 			.base_send_prefix = "PREFIX: ",
1967 			.base_str_prefix = "STR_PREFIX: ",
1968 			.result = "global4.Info: appended1-PREFIX: "
1969 				"[amended1-appended2-TEXT]",
1970 			.result_str_out = "STR_PREFIX: "
1971 				"[amended1-appended2-TEXT]",
1972 		},
1973 		{
1974 			.prefixes = (const struct test_log_event []) {
1975 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1976 				{ TYPE_MESSAGE_AMEND, "amended1-",
1977 				  FLAG_BASE_EVENT },
1978 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
1979 				{ .type = TYPE_END }
1980 			},
1981 			.global_log_prefix = "global4.",
1982 			.base_send_prefix = "PREFIX: ",
1983 			.base_str_prefix = "STR_PREFIX: ",
1984 			.result = "global4.Info: appended1-[amended1-PREFIX: "
1985 				"appended2-TEXT]",
1986 			.result_str_out = "STR_PREFIX: appended2-TEXT",
1987 		},
1988 		{
1989 			.prefixes = (const struct test_log_event []) {
1990 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
1991 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
1992 				{ TYPE_PREFIX_APPEND, "appended2-",
1993 				  FLAG_BASE_EVENT },
1994 				{ .type = TYPE_END }
1995 			},
1996 			.global_log_prefix = "global4.",
1997 			.base_send_prefix = "PREFIX: ",
1998 			.base_str_prefix = "STR_PREFIX: ",
1999 			.result = "global4.Info: "
2000 				"appended1-[amended1-appended2-PREFIX: TEXT]",
2001 			.result_str_out = "STR_PREFIX: TEXT",
2002 		},
2003 		{
2004 			.prefixes = (const struct test_log_event []) {
2005 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2006 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
2007 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2008 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
2009 				{ .type = TYPE_END }
2010 			},
2011 			.global_log_prefix = "global4.",
2012 			.base_send_prefix = "PREFIX: ",
2013 			.base_str_prefix = "STR_PREFIX: ",
2014 			.result = "global4.Info: PREFIX: [amended1-appended1-"
2015 				"[amended2-appended2-TEXT]]",
2016 			.result_str_out = "STR_PREFIX: [amended1-appended1-"
2017 				"[amended2-appended2-TEXT]]",
2018 		},
2019 		{
2020 			.prefixes = (const struct test_log_event []) {
2021 				{ TYPE_MESSAGE_AMEND, "amended1-",
2022 				  FLAG_BASE_EVENT },
2023 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
2024 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2025 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
2026 				{ .type = TYPE_END }
2027 			},
2028 			.global_log_prefix = "global4.",
2029 			.base_send_prefix = "PREFIX: ",
2030 			.base_str_prefix = "STR_PREFIX: ",
2031 			.result = "global4.Info: [amended1-PREFIX: appended1-"
2032 				"[amended2-appended2-TEXT]]",
2033 			.result_str_out = "STR_PREFIX: "
2034 				"appended1-[amended2-appended2-TEXT]",
2035 		},
2036 		{
2037 			.prefixes = (const struct test_log_event []) {
2038 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2039 				{ TYPE_PREFIX_APPEND, "appended1-",
2040 				  FLAG_BASE_EVENT },
2041 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2042 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
2043 				{ .type = TYPE_END }
2044 			},
2045 			.global_log_prefix = "global4.",
2046 			.base_send_prefix = "PREFIX: ",
2047 			.base_str_prefix = "STR_PREFIX: ",
2048 			.result = "global4.Info: [amended1-appended1-PREFIX: "
2049 				"[amended2-appended2-TEXT]]",
2050 			.result_str_out = "STR_PREFIX: "
2051 				"[amended2-appended2-TEXT]",
2052 		},
2053 		{
2054 			.prefixes = (const struct test_log_event []) {
2055 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2056 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
2057 				{ TYPE_MESSAGE_AMEND, "amended2-",
2058 				  FLAG_BASE_EVENT },
2059 				{ TYPE_PREFIX_APPEND, "appended2-", 0 },
2060 				{ .type = TYPE_END }
2061 			},
2062 			.global_log_prefix = "global4.",
2063 			.base_send_prefix = "PREFIX: ",
2064 			.base_str_prefix = "STR_PREFIX: ",
2065 			.result = "global4.Info: [amended1-appended1-"
2066 				"[amended2-PREFIX: appended2-TEXT]]",
2067 			.result_str_out = "STR_PREFIX: appended2-TEXT",
2068 		},
2069 		{
2070 			.prefixes = (const struct test_log_event []) {
2071 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2072 				{ TYPE_PREFIX_APPEND, "appended1-", 0 },
2073 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2074 				{ TYPE_PREFIX_APPEND, "appended2-",
2075 				  FLAG_BASE_EVENT },
2076 				{ .type = TYPE_END }
2077 			},
2078 			.global_log_prefix = "global4.",
2079 			.base_send_prefix = "PREFIX: ",
2080 			.base_str_prefix = "STR_PREFIX: ",
2081 			.result = "global4.Info: [amended1-appended1-"
2082 				"[amended2-appended2-PREFIX: TEXT]]",
2083 			.result_str_out = "STR_PREFIX: TEXT",
2084 		},
2085 		{
2086 			.prefixes = (const struct test_log_event []) {
2087 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
2088 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2089 				{ .type = TYPE_END }
2090 			},
2091 			.base_send_prefix = "PREFIX: ",
2092 			.base_str_prefix = "STR_PREFIX: ",
2093 			.result = "replaced1,Info: [amended1-TEXT]",
2094 			.result_str_out = "[amended1-TEXT]",
2095 		},
2096 		{
2097 			.prefixes = (const struct test_log_event []) {
2098 				{ TYPE_PREFIX_REPLACE, "replaced1,",
2099 				  FLAG_BASE_EVENT },
2100 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2101 				{ .type = TYPE_END }
2102 			},
2103 			.base_send_prefix = "PREFIX: ",
2104 			.base_str_prefix = "STR_PREFIX: ",
2105 			.result = "replaced1,Info: PREFIX: [amended1-TEXT]",
2106 			.result_str_out = "STR_PREFIX: [amended1-TEXT]",
2107 		},
2108 		{
2109 			.prefixes = (const struct test_log_event []) {
2110 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
2111 				{ TYPE_MESSAGE_AMEND, "amended1-",
2112 				  FLAG_BASE_EVENT },
2113 				{ .type = TYPE_END }
2114 			},
2115 			.base_send_prefix = "PREFIX: ",
2116 			.base_str_prefix = "STR_PREFIX: ",
2117 			.result = "replaced1,Info: [amended1-PREFIX: TEXT]",
2118 			.result_str_out = "STR_PREFIX: TEXT",
2119 		},
2120 		{
2121 			.prefixes = (const struct test_log_event []) {
2122 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
2123 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2124 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
2125 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2126 				{ .type = TYPE_END }
2127 			},
2128 			.base_send_prefix = "PREFIX: ",
2129 			.base_str_prefix = "STR_PREFIX: ",
2130 			.result = "replaced2,Info: [amended2-TEXT]",
2131 			.result_str_out = "[amended2-TEXT]",
2132 		},
2133 		{
2134 			.prefixes = (const struct test_log_event []) {
2135 				{ TYPE_PREFIX_REPLACE, "replaced1,",
2136 				  FLAG_BASE_EVENT },
2137 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2138 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
2139 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2140 				{ .type = TYPE_END }
2141 			},
2142 			.base_send_prefix = "PREFIX: ",
2143 			.base_str_prefix = "STR_PREFIX: ",
2144 			.result = "replaced2,Info: [amended2-TEXT]",
2145 			.result_str_out = "[amended2-TEXT]",
2146 		},
2147 		{
2148 			.prefixes = (const struct test_log_event []) {
2149 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
2150 				{ TYPE_MESSAGE_AMEND, "amended1-",
2151 				  FLAG_BASE_EVENT },
2152 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
2153 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2154 				{ .type = TYPE_END }
2155 			},
2156 			.base_send_prefix = "PREFIX: ",
2157 			.base_str_prefix = "STR_PREFIX: ",
2158 			.result = "replaced2,Info: [amended2-TEXT]",
2159 			.result_str_out = "[amended2-TEXT]",
2160 		},
2161 		{
2162 			.prefixes = (const struct test_log_event []) {
2163 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
2164 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2165 				{ TYPE_PREFIX_REPLACE, "replaced2,",
2166 				  FLAG_BASE_EVENT },
2167 				{ TYPE_MESSAGE_AMEND, "amended2-", 0 },
2168 				{ .type = TYPE_END }
2169 			},
2170 			.base_send_prefix = "PREFIX: ",
2171 			.base_str_prefix = "STR_PREFIX: ",
2172 			.result = "replaced2,Info: PREFIX: [amended2-TEXT]",
2173 			.result_str_out = "STR_PREFIX: [amended2-TEXT]",
2174 		},
2175 		{
2176 			.prefixes = (const struct test_log_event []) {
2177 				{ TYPE_PREFIX_REPLACE, "replaced1,", 0 },
2178 				{ TYPE_MESSAGE_AMEND, "amended1-", 0 },
2179 				{ TYPE_PREFIX_REPLACE, "replaced2,", 0 },
2180 				{ TYPE_MESSAGE_AMEND, "amended2-",
2181 				  FLAG_BASE_EVENT },
2182 				{ .type = TYPE_END }
2183 			},
2184 			.base_send_prefix = "PREFIX: ",
2185 			.base_str_prefix = "STR_PREFIX: ",
2186 			.result = "replaced2,Info: [amended2-PREFIX: TEXT]",
2187 			.result_str_out = "STR_PREFIX: TEXT",
2188 		},
2189 		/* Tests in which parent log prefixes are dropped by an event
2190 		   lower in the hierarchy. */
2191 		{
2192 			.prefixes = (const struct test_log_event []) {
2193 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2194 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2195 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2196 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2197 				{ TYPE_PREFIX_APPEND, "appended5.", 0 },
2198 				{ .type = TYPE_END }
2199 			},
2200 			.global_log_prefix = "global3.",
2201 			.result = "global3.Info: "
2202 				"appended1,appended2.appended3."
2203 				"appended4.appended5.TEXT",
2204 			.result_str_out = "appended1,appended2.appended3."
2205 				"appended4.appended5.TEXT",
2206 		},
2207 		{
2208 			.prefixes = (const struct test_log_event []) {
2209 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2210 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2211 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2212 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2213 				{ TYPE_PREFIX_APPEND, "appended5.",
2214 				  FLAG_DROP_PREFIXES_1 },
2215 				{ .type = TYPE_END }
2216 			},
2217 			.global_log_prefix = "global3.",
2218 			.result = "global3.Info: "
2219 				"appended1,appended2.appended3."
2220 				"appended5.TEXT",
2221 			.result_str_out = "appended1,appended2.appended3."
2222 				"appended5.TEXT",
2223 		},
2224 		{
2225 			.prefixes = (const struct test_log_event []) {
2226 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2227 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2228 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2229 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2230 				{ TYPE_PREFIX_APPEND, "appended5.", 0 },
2231 				{ TYPE_SKIP, NULL, FLAG_DROP_PREFIXES_1 },
2232 				{ .type = TYPE_END }
2233 			},
2234 			.global_log_prefix = "global3.",
2235 			.result = "global3.Info: "
2236 				"appended1,appended2.appended3."
2237 				"appended4.TEXT",
2238 			.result_str_out = "appended1,appended2.appended3."
2239 				"appended4.TEXT",
2240 		},
2241 		{
2242 			.prefixes = (const struct test_log_event []) {
2243 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2244 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2245 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2246 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2247 				{ TYPE_PREFIX_APPEND, "appended5.",
2248 				  FLAG_DROP_PREFIXES_2 },
2249 				{ .type = TYPE_END }
2250 			},
2251 			.global_log_prefix = "global3.",
2252 			.result = "global3.Info: "
2253 				"appended1,appended2.appended5.TEXT",
2254 			.result_str_out = "appended1,appended2.appended5.TEXT",
2255 		},
2256 		{
2257 			.prefixes = (const struct test_log_event []) {
2258 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2259 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2260 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2261 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2262 				{ TYPE_PREFIX_APPEND, "appended5.",
2263 				  (FLAG_DROP_PREFIXES_1 |
2264 				   FLAG_DROP_PREFIXES_2) },
2265 				{ .type = TYPE_END }
2266 			},
2267 			.global_log_prefix = "global3.",
2268 			.result = "global3.Info: appended1,appended5.TEXT",
2269 			.result_str_out = "appended1,appended5.TEXT",
2270 		},
2271 		{
2272 			.prefixes = (const struct test_log_event []) {
2273 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2274 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2275 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2276 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2277 				{ TYPE_PREFIX_APPEND, "appended5.",
2278 				  FLAG_DROP_PREFIXES_4 },
2279 				{ .type = TYPE_END }
2280 			},
2281 			.global_log_prefix = "global3.",
2282 			.result = "global3.Info: appended5.TEXT",
2283 			.result_str_out = "appended5.TEXT",
2284 		},
2285 		{
2286 			.prefixes = (const struct test_log_event []) {
2287 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2288 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2289 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2290 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2291 				{ TYPE_PREFIX_APPEND, "appended5.",
2292 				  (FLAG_DROP_PREFIXES_1 |
2293 				   FLAG_DROP_PREFIXES_2 |
2294 				   FLAG_DROP_PREFIXES_4) },
2295 				{ .type = TYPE_END }
2296 			},
2297 			.global_log_prefix = "global3.",
2298 			.result = "global3.Info: appended5.TEXT",
2299 			.result_str_out = "appended5.TEXT",
2300 		},
2301 		{
2302 			.prefixes = (const struct test_log_event []) {
2303 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2304 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2305 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2306 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2307 				{ TYPE_PREFIX_APPEND, "appended5.", 0 },
2308 				{ TYPE_SKIP, NULL, (FLAG_DROP_PREFIXES_1 |
2309 						    FLAG_DROP_PREFIXES_2 |
2310 						    FLAG_DROP_PREFIXES_4) },
2311 				{ .type = TYPE_END }
2312 			},
2313 			.global_log_prefix = "global3.",
2314 			.result = "global3.Info: TEXT",
2315 			.result_str_out = "TEXT",
2316 		},
2317 		{
2318 			.prefixes = (const struct test_log_event []) {
2319 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2320 				{ TYPE_PREFIX_APPEND, "appended2.",
2321 				  FLAG_DROP_PREFIXES_1 },
2322 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2323 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2324 				{ TYPE_PREFIX_APPEND, "appended5.",
2325 				  FLAG_DROP_PREFIXES_1 },
2326 				{ .type = TYPE_END }
2327 			},
2328 			.global_log_prefix = "global3.",
2329 			.result = "global3.Info: "
2330 				"appended2.appended3.appended5.TEXT",
2331 			.result_str_out = "appended2.appended3.appended5.TEXT",
2332 		},
2333 		{
2334 			.prefixes = (const struct test_log_event []) {
2335 				{ TYPE_PREFIX_APPEND, "appended1,",
2336 				  FLAG_DROP_PREFIXES_1 },
2337 				{ TYPE_PREFIX_APPEND, "appended2.",
2338 				  FLAG_DROP_PREFIXES_1 },
2339 				{ TYPE_PREFIX_APPEND, "appended3.",
2340 				  FLAG_DROP_PREFIXES_1 },
2341 				{ TYPE_PREFIX_APPEND, "appended4.",
2342 				  FLAG_DROP_PREFIXES_1 },
2343 				{ TYPE_PREFIX_APPEND, "appended5.",
2344 				  FLAG_DROP_PREFIXES_1 },
2345 				{ .type = TYPE_END }
2346 			},
2347 			.global_log_prefix = "global3.",
2348 			.result = "global3.Info: appended5.TEXT",
2349 			.result_str_out = "appended5.TEXT",
2350 		},
2351 		{
2352 			.prefixes = (const struct test_log_event []) {
2353 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2354 				{ .type = TYPE_SKIP },
2355 				{ TYPE_PREFIX_APPEND, "appended2.",
2356 				  FLAG_DROP_PREFIXES_1 },
2357 				{ .type = TYPE_SKIP },
2358 				{ TYPE_PREFIX_APPEND, "appended3.", 0 },
2359 				{ .type = TYPE_SKIP },
2360 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2361 				{ .type = TYPE_SKIP },
2362 				{ TYPE_PREFIX_APPEND, "appended5.",
2363 				  FLAG_DROP_PREFIXES_1 },
2364 				{ .type = TYPE_SKIP },
2365 				{ .type = TYPE_END }
2366 			},
2367 			.global_log_prefix = "global3.",
2368 			.result = "global3.Info: "
2369 				"appended2.appended3.appended5.TEXT",
2370 			.result_str_out = "appended2.appended3.appended5.TEXT",
2371 		},
2372 		{
2373 			.prefixes = (const struct test_log_event []) {
2374 				{ TYPE_PREFIX_APPEND, "appended1,", 0 },
2375 				{ TYPE_PREFIX_APPEND, "appended2.", 0 },
2376 				{ TYPE_PREFIX_APPEND, "appended3.",
2377 				  FLAG_DROP_PREFIXES_1 },
2378 				{ TYPE_PREFIX_APPEND, "appended4.", 0 },
2379 				{ TYPE_PREFIX_APPEND, "appended5.",
2380 				  (FLAG_DROP_PREFIXES_1 |
2381 				   FLAG_DROP_PREFIXES_2) },
2382 				{ .type = TYPE_END }
2383 			},
2384 			.global_log_prefix = "global3.",
2385 			.result = "global3.Info: appended5.TEXT",
2386 			.result_str_out = "appended5.TEXT",
2387 		},
2388 	};
2389 
2390 	test_begin("event log message");
2391 
2392 	failure_callback_t *orig_fatal, *orig_error, *orig_info, *orig_debug;
2393 	i_get_failure_handlers(&orig_fatal, &orig_error, &orig_info, &orig_debug);
2394 	i_set_info_handler(info_handler);
2395 	for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) T_BEGIN {
2396 		const struct test_log *test = &tests[i];
2397 		struct event_log_params params = {
2398 			.log_type = LOG_TYPE_INFO,
2399 			.base_send_prefix = test->base_send_prefix,
2400 			.base_str_prefix = test->base_str_prefix,
2401 			.no_send = ((test->flags & FLAG_NO_SEND) != 0),
2402 		};
2403 
2404 		i_free(test_output);
2405 		if (test->global_log_prefix != NULL)
2406 			i_set_failure_prefix("%s", test->global_log_prefix);
2407 		else
2408 			i_set_failure_prefix("UNEXPECTED GLOBAL PREFIX");
2409 
2410 		struct event *event, *parent;
2411 		event = parent = event_create(NULL);
2412 		for (unsigned int j = 0; test->prefixes[j].type != TYPE_END; j++) {
2413 			unsigned int drop_prefixes = 0;
2414 
2415 			if (event == NULL) {
2416 				struct event *child = event_create(parent);
2417 				event_unref(&parent);
2418 				event = parent = child;
2419 			}
2420 			if ((test->prefixes[j].flags & FLAG_BASE_EVENT) != 0) {
2421 				i_assert(params.base_event == NULL);
2422 				params.base_event = event;
2423 			}
2424 			if ((test->prefixes[j].flags &
2425 			     FLAG_DROP_PREFIXES_1) != 0)
2426 				drop_prefixes += 1;
2427 			if ((test->prefixes[j].flags &
2428 			     FLAG_DROP_PREFIXES_2) != 0)
2429 				drop_prefixes += 2;
2430 			if ((test->prefixes[j].flags &
2431 			     FLAG_DROP_PREFIXES_4) != 0)
2432 				drop_prefixes += 4;
2433 			event_drop_parent_log_prefixes(event, drop_prefixes);
2434 
2435 			switch (test->prefixes[j].type) {
2436 			case TYPE_END:
2437 				i_unreached();
2438 			case TYPE_PREFIX_APPEND:
2439 				event_set_append_log_prefix(event, test->prefixes[j].str);
2440 				break;
2441 			case TYPE_PREFIX_REPLACE:
2442 				event_replace_log_prefix(event, test->prefixes[j].str);
2443 				break;
2444 			case TYPE_PREFIX_APPEND_CB:
2445 				event_set_log_prefix_callback(event, FALSE,
2446 							      test_event_log_prefix_cb,
2447 							      (char*)test->prefixes[j].str);
2448 				break;
2449 			case TYPE_PREFIX_REPLACE_CB:
2450 				event_set_log_prefix_callback(event, TRUE,
2451 							      test_event_log_prefix_cb,
2452 							      (char*)test->prefixes[j].str);
2453 				break;
2454 			case TYPE_MESSAGE_AMEND:
2455 				event_set_log_message_callback(event,
2456 							       test_event_log_message_cb,
2457 							       (char*)test->prefixes[j].str);
2458 				break;
2459 			case TYPE_SKIP:
2460 				break;
2461 			}
2462 			event = NULL;
2463 		}
2464 		event = parent;
2465 
2466 		if (test->result_str_out != NULL) {
2467 			/* Use small value so buffer size grows. This way the
2468 			   unit test fails if anyone attempts to add data-stack
2469 			   frame to event_log(). */
2470 			params.base_str_out = t_str_new(1);
2471 		}
2472 		event_log(event, &params, "TEXT");
2473 
2474 		test_assert_strcmp(test->result, test_output);
2475 		if (test->result_str_out != NULL) {
2476 			test_assert_strcmp(test->result_str_out,
2477 					   str_c(params.base_str_out));
2478 		}
2479 		event_unref(&event);
2480 	} T_END;
2481 	i_set_info_handler(orig_info);
2482 	i_unset_failure_prefix();
2483 	i_free(test_output);
2484 	test_end();
2485 }
2486 
test_event_duration()2487 static void test_event_duration()
2488 {
2489 	uintmax_t duration;
2490 	test_begin("event duration");
2491 	struct event *e = event_create(NULL);
2492 	usleep(10);
2493 	e_info(e, "Submit event");
2494 	event_get_last_duration(e, &duration);
2495 	test_assert(duration > 0);
2496 	event_unref(&e);
2497 	test_end();
2498 }
2499 
test_event_log_level(void)2500 static void test_event_log_level(void)
2501 {
2502 	test_begin("event log level");
2503 	failure_callback_t *orig_fatal, *orig_error, *orig_info, *orig_debug;
2504 	i_get_failure_handlers(&orig_fatal, &orig_error, &orig_info, &orig_debug);
2505 	i_set_info_handler(info_handler);
2506 	i_set_error_handler(error_handler);
2507 
2508 	struct event *event = event_create(NULL);
2509 	event_set_min_log_level(event, LOG_TYPE_WARNING);
2510 	errno = EACCES;
2511 	e_info(event, "Info event");
2512 	test_assert(test_output == NULL);
2513 	e_warning(event, "Warning event");
2514 	test_assert_strcmp(test_output, "Warning: Warning event");
2515 	event_unref(&event);
2516 	i_set_info_handler(orig_info);
2517 	i_set_error_handler(orig_error);
2518 	i_free(test_output);
2519 	test_assert(errno == EACCES);
2520 	test_end();
2521 }
2522 
test_event_log(void)2523 void test_event_log(void)
2524 {
2525 	test_event_log_message();
2526 	test_event_duration();
2527 	test_event_log_level();
2528 }
2529