Skip to content

Commit 280c6b5

Browse files
zshuang0316edsiper
authored andcommitted
tests: add test for ignore_active_older_files re-pickup on mtime update
Add two runtime tests that verify a file aged out by ignore_active_older_files is re-added to monitoring when new content updates its mtime, and that reading resumes from the saved offset: - reread_on_update: uses read_newly_discovered_files_from_head=false - reread_on_update_default_read_from_head: uses the default (true), verifying set_file_position honours the saved offset even when ctx->read_from_head is true Signed-off-by: zshuang0316 <zshuang0316@users.noreply.github.com> Signed-off-by: zshuang0316 <zshuang0316@163.com>
1 parent 0264c0b commit 280c6b5

1 file changed

Lines changed: 190 additions & 0 deletions

File tree

tests/runtime/in_tail.c

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2042,6 +2042,194 @@ void flb_test_in_tail_ignore_active_older_files()
20422042
test_tail_ctx_destroy(ctx);
20432043
}
20442044

2045+
/*
2046+
* Verify that a file excluded by ignore_active_older_files is re-picked up
2047+
* once its mtime is refreshed by a new write.
2048+
*
2049+
* Sequence:
2050+
* 1. Write msg1 → engine reads it (count = 1)
2051+
* 2. Wait 4 s → purge fires (rotate_wait=1s), file is >2s old; inode
2052+
* registered as aged-out and file removed from monitoring
2053+
* 3. Write msg2 → mtime is now fresh
2054+
* 4. Wait 3 s → scan fires (refresh_interval=1s), sees fresh mtime;
2055+
* unregisters aged-out entry and re-adds file at the
2056+
* stored offset (file->offset saved at age-out time);
2057+
* engine reads only msg2 (count += 1)
2058+
* 5. Assert count == 2
2059+
*/
2060+
void flb_test_in_tail_ignore_active_older_files_reread_on_update()
2061+
{
2062+
struct flb_lib_out_cb cb_data;
2063+
struct test_tail_ctx *ctx;
2064+
char *file[] = {"source_file_reread.log"};
2065+
char *path = "source_file_reread.log";
2066+
char *msg = "TEST LINE";
2067+
const int expected = 2;
2068+
const int expected_before_rotate = 1;
2069+
int ret;
2070+
int num;
2071+
int unused;
2072+
2073+
clear_output_num();
2074+
2075+
cb_data.cb = cb_count_msgpack;
2076+
cb_data.data = &unused;
2077+
2078+
ctx = test_tail_ctx_create(&cb_data, &file[0], sizeof(file)/sizeof(char *), FLB_TRUE);
2079+
if (!TEST_CHECK(ctx != NULL)) {
2080+
TEST_MSG("test_ctx_create failed");
2081+
return;
2082+
}
2083+
2084+
ret = flb_input_set(ctx->flb, ctx->o_ffd,
2085+
"path", path,
2086+
"ignore_older", "2s",
2087+
"rotate_wait", "1s",
2088+
"refresh_interval", "1s",
2089+
"read_newly_discovered_files_from_head", "false",
2090+
"ignore_active_older_files", "on",
2091+
NULL);
2092+
TEST_CHECK(ret == 0);
2093+
2094+
ret = flb_start(ctx->flb);
2095+
if (!TEST_CHECK(ret == 0)) {
2096+
test_tail_ctx_destroy(ctx);
2097+
return;
2098+
}
2099+
2100+
/* Write first message and allow it to be flushed */
2101+
ret = write_msg(ctx, msg, strlen(msg));
2102+
if (!TEST_CHECK(ret > 0)) {
2103+
test_tail_ctx_destroy(ctx);
2104+
return;
2105+
}
2106+
2107+
/* Wait until msg1 is consumed before starting the aging clock. */
2108+
wait_expected_num_with_timeout(5000, expected_before_rotate, &num);
2109+
if (!TEST_CHECK(num == expected_before_rotate)) {
2110+
TEST_MSG("msg1 not consumed in time. got=%d", num);
2111+
test_tail_ctx_destroy(ctx);
2112+
return;
2113+
}
2114+
2115+
/*
2116+
* Wait long enough for the purge callback (rotate_wait=1s) to fire and
2117+
* detect that the file's mtime is older than ignore_older=2s, which
2118+
* removes the file from monitoring and registers its inode as aged-out.
2119+
*/
2120+
flb_time_msleep(4000);
2121+
2122+
/* Append new content: this updates mtime so the file is no longer old */
2123+
ret = write_msg(ctx, msg, strlen(msg));
2124+
if (!TEST_CHECK(ret > 0)) {
2125+
test_tail_ctx_destroy(ctx);
2126+
return;
2127+
}
2128+
2129+
/*
2130+
* Wait for the scan callback (refresh_interval=1s) to re-evaluate the
2131+
* aged-out entry, find the fresh mtime, unregister the entry, and
2132+
* re-add the file. The file is re-added at the stored offset (the read
2133+
* position saved when the file was aged out), so only msg2 — the content
2134+
* that refreshed the mtime — is flushed (count += 1).
2135+
*/
2136+
wait_expected_num_with_timeout(5000, expected, &num);
2137+
2138+
if (!TEST_CHECK(num == expected)) {
2139+
TEST_MSG("output num error. expect=%d got=%d", expected, num);
2140+
}
2141+
2142+
test_tail_ctx_destroy(ctx);
2143+
}
2144+
2145+
void flb_test_in_tail_ignore_active_older_files_reread_on_update_default_read_from_head()
2146+
{
2147+
struct flb_lib_out_cb cb_data;
2148+
struct test_tail_ctx *ctx;
2149+
char *file[] = {"source_file_reread_default.log"};
2150+
char *path = "source_file_reread_default.log";
2151+
char *msg = "TEST LINE";
2152+
const int expected = 2;
2153+
const int expected_before_rotate = 1;
2154+
int ret;
2155+
int num;
2156+
int unused;
2157+
2158+
clear_output_num();
2159+
2160+
cb_data.cb = cb_count_msgpack;
2161+
cb_data.data = &unused;
2162+
2163+
ctx = test_tail_ctx_create(&cb_data, &file[0], sizeof(file)/sizeof(char *), FLB_TRUE);
2164+
if (!TEST_CHECK(ctx != NULL)) {
2165+
TEST_MSG("test_ctx_create failed");
2166+
return;
2167+
}
2168+
2169+
/*
2170+
* Do not set read_newly_discovered_files_from_head — leave it at its
2171+
* default (true). The fix in set_file_position must honour the saved
2172+
* offset even when ctx->read_from_head is true, so only msg2 is flushed
2173+
* on re-pickup rather than replaying msg1 from the start.
2174+
*/
2175+
ret = flb_input_set(ctx->flb, ctx->o_ffd,
2176+
"path", path,
2177+
"ignore_older", "2s",
2178+
"rotate_wait", "1s",
2179+
"refresh_interval", "1s",
2180+
"ignore_active_older_files", "on",
2181+
NULL);
2182+
TEST_CHECK(ret == 0);
2183+
2184+
ret = flb_start(ctx->flb);
2185+
if (!TEST_CHECK(ret == 0)) {
2186+
test_tail_ctx_destroy(ctx);
2187+
return;
2188+
}
2189+
2190+
/* Write first message and allow it to be flushed */
2191+
ret = write_msg(ctx, msg, strlen(msg));
2192+
if (!TEST_CHECK(ret > 0)) {
2193+
test_tail_ctx_destroy(ctx);
2194+
return;
2195+
}
2196+
2197+
/* Wait until msg1 is consumed before starting the aging clock. */
2198+
wait_expected_num_with_timeout(5000, expected_before_rotate, &num);
2199+
if (!TEST_CHECK(num == expected_before_rotate)) {
2200+
TEST_MSG("msg1 not consumed in time. got=%d", num);
2201+
test_tail_ctx_destroy(ctx);
2202+
return;
2203+
}
2204+
2205+
/*
2206+
* Wait long enough for the purge callback (rotate_wait=1s) to fire and
2207+
* age out the file.
2208+
*/
2209+
flb_time_msleep(4000);
2210+
2211+
/* Append new content: updates mtime so the file is no longer old */
2212+
ret = write_msg(ctx, msg, strlen(msg));
2213+
if (!TEST_CHECK(ret > 0)) {
2214+
test_tail_ctx_destroy(ctx);
2215+
return;
2216+
}
2217+
2218+
/*
2219+
* The scan callback re-adds the file from the stored offset. With the
2220+
* default read_newly_discovered_files_from_head=true, set_file_position
2221+
* must still seek to the saved offset so msg1 is not replayed.
2222+
* Total expected: 1 (msg1) + 1 (msg2) = 2.
2223+
*/
2224+
wait_expected_num_with_timeout(5000, expected, &num);
2225+
2226+
if (!TEST_CHECK(num == expected)) {
2227+
TEST_MSG("output num error. expect=%d got=%d", expected, num);
2228+
}
2229+
2230+
test_tail_ctx_destroy(ctx);
2231+
}
2232+
20452233
void flb_test_inotify_watcher_false()
20462234
{
20472235
struct flb_lib_out_cb cb_data;
@@ -2749,6 +2937,8 @@ TEST_LIST = {
27492937
{"skip_empty_lines_crlf", flb_test_skip_empty_lines_crlf},
27502938
{"ignore_older", flb_test_ignore_older},
27512939
{"ignore_active_older_files", flb_test_in_tail_ignore_active_older_files},
2940+
{"ignore_active_older_files_reread_on_update", flb_test_in_tail_ignore_active_older_files_reread_on_update},
2941+
{"ignore_active_older_files_reread_on_update_default_read_from_head", flb_test_in_tail_ignore_active_older_files_reread_on_update_default_read_from_head},
27522942
#ifdef FLB_HAVE_INOTIFY
27532943
{"inotify_watcher_false", flb_test_inotify_watcher_false},
27542944
{"inotify_pause_collectors", flb_test_inotify_pause_collectors},

0 commit comments

Comments
 (0)