Skip to content

Commit a8bd9e4

Browse files
committed
tests: internal: multiline: add test for issue #10927
Signed-off-by: Eduardo Silva <[email protected]>
1 parent 235f1c7 commit a8bd9e4

File tree

1 file changed

+90
-3
lines changed

1 file changed

+90
-3
lines changed

tests/internal/multiline.c

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,40 @@ struct record_check container_mix_input[] = {
107107
{"{\"log\": \"dd-err\\n\", \"stream\": \"stderr\", \"time\": \"2021-02-01T16:45:03.01234z\"}"},
108108
};
109109

110+
/*
111+
* The docker parser should emit each container fragment as soon as the log
112+
* stream provides a newline. CRI lines handled by the chained parser are
113+
* expected to flush immediately even if the docker stream still has buffered
114+
* fragments waiting for a later newline (e.g. "bb" + "cc" + "dd-out\n").
115+
*/
110116
struct record_check container_mix_output[] = {
111117
{"a1\n"},
112118
{"a2\n"},
113119
{"ddee\n"},
114-
{"bbccdd-out\n"},
115-
{"dd-err\n"},
116120
{"single full"},
117121
{"1a. some multiline log"},
118122
{"1b. some multiline log"},
123+
{"bbccdd-out\n"},
124+
{"dd-err\n"},
125+
};
126+
127+
/*
128+
* Regression guard: when docker is the first parser in the chain and a CRI
129+
* record arrives, the docker parser must decline the line so the CRI parser
130+
* can consume it instead of buffering the payload until the flush timer
131+
* expires. The strings below mimic container runtime output without trailing
132+
* newlines as seen in the reported issue.
133+
*/
134+
struct record_check docker_cri_chain_input[] = {
135+
{"2025-09-22T19:07:06.115398289Z stdout F first message"},
136+
{"2025-09-22T19:07:06.116725604Z stdout F second message"},
137+
{"2025-09-22T19:07:08.582112316Z stdout F third message"},
138+
};
139+
140+
struct record_check docker_cri_chain_output[] = {
141+
{"first message"},
142+
{"second message"},
143+
{"third message"},
119144
};
120145

121146
/* Java stacktrace detection */
@@ -603,6 +628,68 @@ static void test_container_mix()
603628
flb_config_exit(config);
604629
}
605630

631+
static void test_parser_docker_cri_chain()
632+
{
633+
int i;
634+
int len;
635+
int ret;
636+
int entries;
637+
int expected;
638+
uint64_t stream_id;
639+
struct record_check *r;
640+
struct flb_config *config;
641+
struct flb_time tm;
642+
struct flb_ml *ml;
643+
struct flb_ml_parser_ins *mlp_i;
644+
struct expected_result res = {0};
645+
646+
/* Expected results context */
647+
res.key = "log";
648+
res.out_records = docker_cri_chain_output;
649+
650+
/* Initialize environment */
651+
config = flb_config_init();
652+
653+
/* Create docker multiline mode */
654+
ml = flb_ml_create(config, "docker-cri-chain");
655+
TEST_CHECK(ml != NULL);
656+
657+
/* Generate an instance of multiline docker parser */
658+
mlp_i = flb_ml_parser_instance_create(ml, "docker");
659+
TEST_CHECK(mlp_i != NULL);
660+
661+
/* Load instances of the parsers for current 'ml' context */
662+
mlp_i = flb_ml_parser_instance_create(ml, "cri");
663+
TEST_CHECK(mlp_i != NULL);
664+
665+
ret = flb_ml_stream_create(ml, "docker-cri-chain", -1, flush_callback,
666+
(void *) &res, &stream_id);
667+
TEST_CHECK(ret == 0);
668+
669+
entries = sizeof(docker_cri_chain_input) / sizeof(struct record_check);
670+
for (i = 0; i < entries; i++) {
671+
r = &docker_cri_chain_input[i];
672+
len = strlen(r->buf);
673+
674+
flb_time_get(&tm);
675+
676+
/* Package as msgpack */
677+
flb_ml_append_text(ml, stream_id, &tm, r->buf, len);
678+
}
679+
680+
/* Flush any pending data to ensure no buffered records remain */
681+
flb_ml_flush_pending_now(ml);
682+
683+
expected = sizeof(docker_cri_chain_output) / sizeof(struct record_check);
684+
TEST_CHECK(res.current_record == expected);
685+
686+
if (ml) {
687+
flb_ml_destroy(ml);
688+
}
689+
690+
flb_config_exit(config);
691+
}
692+
606693
static void test_parser_java()
607694
{
608695
int i;
@@ -1468,7 +1555,6 @@ static void test_buffer_limit_truncation()
14681555
struct flb_ml *ml;
14691556
struct flb_ml_parser *mlp;
14701557
struct flb_ml_parser_ins *mlp_i;
1471-
struct flb_parser *p;
14721558
struct flb_time tm;
14731559

14741560
/*
@@ -1561,6 +1647,7 @@ TEST_LIST = {
15611647
/* Normal features tests */
15621648
{ "parser_docker", test_parser_docker},
15631649
{ "parser_cri", test_parser_cri},
1650+
{ "parser_docker_cri_chain", test_parser_docker_cri_chain},
15641651
{ "parser_java", test_parser_java},
15651652
{ "parser_python", test_parser_python},
15661653
{ "parser_ruby", test_parser_ruby},

0 commit comments

Comments
 (0)