Skip to content

Commit 9b72af5

Browse files
leogrpoiana
authored andcommitted
chore(unit_tests): capture feature testing
Signed-off-by: Leonardo Grasso <[email protected]>
1 parent ce038d9 commit 9b72af5

2 files changed

Lines changed: 225 additions & 0 deletions

File tree

unit_tests/engine/test_rule_loader.cpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,3 +1571,137 @@ TEST_F(test_falco_engine, deprecated_evt_dir_via_macro_folded_scalar_condition_s
15711571
}
15721572
FAIL() << "no LOAD_DEPRECATED_ITEM warning found: " << m_load_result_string;
15731573
}
1574+
1575+
// Capture field tests
1576+
1577+
TEST_F(test_falco_engine, rule_capture_enabled) {
1578+
std::string rules_content = R"END(
1579+
- rule: test_rule
1580+
desc: test rule
1581+
condition: evt.type = close
1582+
output: user=%user.name
1583+
priority: WARNING
1584+
capture: true
1585+
)END";
1586+
1587+
std::string rule_name = "test_rule";
1588+
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
1589+
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
1590+
1591+
auto rule_description = m_engine->describe_rule(&rule_name, {});
1592+
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), true);
1593+
}
1594+
1595+
TEST_F(test_falco_engine, rule_capture_disabled_by_default) {
1596+
std::string rules_content = R"END(
1597+
- rule: test_rule
1598+
desc: test rule
1599+
condition: evt.type = close
1600+
output: user=%user.name
1601+
priority: INFO
1602+
)END";
1603+
1604+
std::string rule_name = "test_rule";
1605+
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
1606+
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
1607+
1608+
auto rule_description = m_engine->describe_rule(&rule_name, {});
1609+
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), false);
1610+
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
1611+
0u);
1612+
}
1613+
1614+
TEST_F(test_falco_engine, rule_capture_duration) {
1615+
std::string rules_content = R"END(
1616+
- rule: test_rule
1617+
desc: test rule
1618+
condition: evt.type = close
1619+
output: user=%user.name
1620+
priority: WARNING
1621+
capture: true
1622+
capture_duration: 10000
1623+
)END";
1624+
1625+
std::string rule_name = "test_rule";
1626+
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
1627+
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
1628+
1629+
auto rule_description = m_engine->describe_rule(&rule_name, {});
1630+
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
1631+
10000u);
1632+
}
1633+
1634+
TEST_F(test_falco_engine, rule_override_capture_replace) {
1635+
std::string rules_content = R"END(
1636+
- rule: test_rule
1637+
desc: test rule
1638+
condition: evt.type = close
1639+
output: user=%user.name
1640+
priority: WARNING
1641+
capture: true
1642+
1643+
- rule: test_rule
1644+
capture: false
1645+
override:
1646+
capture: replace
1647+
)END";
1648+
1649+
std::string rule_name = "test_rule";
1650+
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
1651+
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
1652+
1653+
auto rule_description = m_engine->describe_rule(&rule_name, {});
1654+
ASSERT_EQ(rule_description["rules"][0]["info"]["capture"].template get<bool>(), false);
1655+
}
1656+
1657+
TEST_F(test_falco_engine, rule_override_capture_duration_replace) {
1658+
std::string rules_content = R"END(
1659+
- rule: test_rule
1660+
desc: test rule
1661+
condition: evt.type = close
1662+
output: user=%user.name
1663+
priority: WARNING
1664+
capture: true
1665+
capture_duration: 5000
1666+
1667+
- rule: test_rule
1668+
capture_duration: 15000
1669+
override:
1670+
capture_duration: replace
1671+
)END";
1672+
1673+
std::string rule_name = "test_rule";
1674+
ASSERT_TRUE(load_rules(rules_content, "rules.yaml")) << m_load_result_string;
1675+
ASSERT_VALIDATION_STATUS(yaml_helper::validation_ok) << m_load_result->schema_validation();
1676+
1677+
auto rule_description = m_engine->describe_rule(&rule_name, {});
1678+
ASSERT_EQ(rule_description["rules"][0]["info"]["capture_duration"].template get<uint32_t>(),
1679+
15000u);
1680+
}
1681+
1682+
TEST_F(test_falco_engine, rule_capture_duration_wrong_type) {
1683+
std::string rules_content = R"END(
1684+
- rule: test_rule
1685+
desc: test rule
1686+
condition: evt.type = close
1687+
output: user=%user.name
1688+
priority: INFO
1689+
capture_duration: "not_a_number"
1690+
)END";
1691+
1692+
ASSERT_FALSE(load_rules(rules_content, "rules.yaml"));
1693+
}
1694+
1695+
TEST_F(test_falco_engine, rule_capture_wrong_type) {
1696+
std::string rules_content = R"END(
1697+
- rule: test_rule
1698+
desc: test rule
1699+
condition: evt.type = close
1700+
output: user=%user.name
1701+
priority: INFO
1702+
capture: "yes"
1703+
)END";
1704+
1705+
ASSERT_TRUE(load_rules(rules_content, "rules.yaml"));
1706+
ASSERT_VALIDATION_STATUS(yaml_helper::validation_failed) << m_load_result->schema_validation();
1707+
}

unit_tests/falco/test_capture.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717

1818
#include <falco/app/actions/helpers.h>
1919
#include <falco/configuration.h>
20+
#include <libsinsp/utils.h>
2021
#include <gtest/gtest.h>
2122

2223
TEST(Capture, generate_scap_file_path_realistic_scenario) {
@@ -79,6 +80,7 @@ TEST(Capture, capture_config_disabled_by_default) {
7980
EXPECT_EQ(config.m_capture_path_prefix, "/tmp/falco");
8081
EXPECT_EQ(config.m_capture_mode, capture_mode_t::RULES);
8182
EXPECT_EQ(config.m_capture_default_duration_ns, 5000 * 1000000LL); // 5 seconds in ns
83+
EXPECT_EQ(config.m_capture_max_file_size_mb, 0u);
8284
}
8385

8486
TEST(Capture, capture_config_enabled_rules_mode) {
@@ -132,3 +134,92 @@ TEST(Capture, capture_config_invalid_mode) {
132134
// Should throw an exception for invalid mode
133135
EXPECT_THROW(res = config.init_from_content(config_content, {}), std::logic_error);
134136
}
137+
138+
TEST(Capture, capture_config_with_max_file_size_mb) {
139+
std::string config_content = R"(
140+
capture:
141+
enabled: true
142+
max_file_size_mb: 100
143+
)";
144+
145+
falco_configuration config;
146+
config_loaded_res res;
147+
ASSERT_NO_THROW(res = config.init_from_content(config_content, {}));
148+
149+
EXPECT_EQ(config.m_capture_max_file_size_mb, 100u);
150+
}
151+
152+
TEST(Capture, capture_config_with_all_limits) {
153+
std::string config_content = R"(
154+
capture:
155+
enabled: true
156+
default_duration: 15000
157+
max_file_size_mb: 500
158+
)";
159+
160+
falco_configuration config;
161+
config_loaded_res res;
162+
ASSERT_NO_THROW(res = config.init_from_content(config_content, {}));
163+
164+
EXPECT_EQ(config.m_capture_default_duration_ns, 15000 * 1000000LL);
165+
EXPECT_EQ(config.m_capture_max_file_size_mb, 500u);
166+
}
167+
168+
TEST(Capture, capture_config_rejects_out_of_range_max_file_size_mb) {
169+
// Exceeds the schema maximum (1 TB in MB)
170+
std::string config_content = R"(
171+
capture:
172+
enabled: true
173+
max_file_size_mb: 99999999999
174+
)";
175+
176+
falco_configuration config;
177+
config_loaded_res res;
178+
ASSERT_NO_THROW(res = config.init_from_content(config_content, {}));
179+
for(const auto& pair : res) {
180+
EXPECT_TRUE(sinsp_utils::startswith(pair.second, yaml_helper::validation_failed))
181+
<< pair.second;
182+
}
183+
}
184+
185+
TEST(Capture, check_capture_stop_no_stop) {
186+
// Deadline in the future, no size cap
187+
EXPECT_EQ(falco::app::actions::check_capture_stop(100, 200, 0, 0),
188+
falco::app::actions::capture_stop_reason::NONE);
189+
// Deadline in the future, size under cap
190+
EXPECT_EQ(falco::app::actions::check_capture_stop(100, 200, 1024, 1),
191+
falco::app::actions::capture_stop_reason::NONE);
192+
}
193+
194+
TEST(Capture, check_capture_stop_time_deadline) {
195+
// Exactly at deadline stops (>=)
196+
EXPECT_EQ(falco::app::actions::check_capture_stop(200, 200, 0, 0),
197+
falco::app::actions::capture_stop_reason::TIME_DEADLINE);
198+
// Past deadline
199+
EXPECT_EQ(falco::app::actions::check_capture_stop(201, 200, 0, 0),
200+
falco::app::actions::capture_stop_reason::TIME_DEADLINE);
201+
}
202+
203+
TEST(Capture, check_capture_stop_size_limit) {
204+
// 1 MB cap, written exactly 1 MB -> stops
205+
EXPECT_EQ(falco::app::actions::check_capture_stop(100, 200, 1024 * 1024, 1),
206+
falco::app::actions::capture_stop_reason::SIZE_LIMIT);
207+
// 1 MB cap, written over
208+
EXPECT_EQ(falco::app::actions::check_capture_stop(100, 200, 2 * 1024 * 1024, 1),
209+
falco::app::actions::capture_stop_reason::SIZE_LIMIT);
210+
// 1 MB cap, written just under -> no stop
211+
EXPECT_EQ(falco::app::actions::check_capture_stop(100, 200, 1024 * 1024 - 1, 1),
212+
falco::app::actions::capture_stop_reason::NONE);
213+
}
214+
215+
TEST(Capture, check_capture_stop_zero_means_unlimited) {
216+
// 0 MB cap means unlimited, even with huge written_bytes
217+
EXPECT_EQ(falco::app::actions::check_capture_stop(100, 200, UINT64_MAX, 0),
218+
falco::app::actions::capture_stop_reason::NONE);
219+
}
220+
221+
TEST(Capture, check_capture_stop_time_wins_when_both_tripped) {
222+
// Both conditions met: time is reported first (matches check order)
223+
EXPECT_EQ(falco::app::actions::check_capture_stop(200, 200, 10 * 1024 * 1024, 1),
224+
falco::app::actions::capture_stop_reason::TIME_DEADLINE);
225+
}

0 commit comments

Comments
 (0)