Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Anilm3 committed Nov 26, 2024
1 parent ba3d3c8 commit c01b719
Show file tree
Hide file tree
Showing 3 changed files with 375 additions and 3 deletions.
9 changes: 9 additions & 0 deletions tests/unit/clock_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,13 @@ TEST(TestTimer, EndlessTimer)
EXPECT_FALSE(deadline.expired());
}

TEST(TestTimer, TimerExpirationBeyondSizeLimit)
{
ddwaf::base_timer<5> deadline{std::chrono::nanoseconds::max()};
EXPECT_FALSE(deadline.expired());

std::this_thread::sleep_for(1ms);
EXPECT_FALSE(deadline.expired());
}

} // namespace
337 changes: 334 additions & 3 deletions tests/unit/module_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ TEST(TestModule, SingleRuleMatch)

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
mod.eval(events, store, cache, {}, {}, deadline);

auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::monitor);
EXPECT_EQ(events.size(), 1);
}

Expand All @@ -62,11 +62,341 @@ TEST(TestModule, SingleRuleMatch)
std::vector<event> events;
ddwaf::timer deadline = endless_timer();
mod.eval(events, store, cache, {}, {}, deadline);
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::none);
EXPECT_EQ(events.size(), 0);
}
}

TEST(TestModule, MultipleMonitoringRuleMatch)
{
std::vector<std::shared_ptr<core_rule>> rules;
{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(
std::make_shared<core_rule>("id1", "name", std::move(tags), builder.build()));
}

{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(
std::make_shared<core_rule>("id2", "name", std::move(tags), builder.build()));
}

rule_module_builder mod_builder{base_rule_precedence, null_grouping_key};
for (const auto &rule : rules) { mod_builder.insert(rule.get()); }

auto mod = mod_builder.build();

rule_module_cache cache;
mod.init_cache(cache);

ddwaf::object_store store;
{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.1"));

store.insert(root);

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::monitor);
EXPECT_EQ(events.size(), 2);
}

{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.1"));

store.insert(root);
std::vector<event> events;
ddwaf::timer deadline = endless_timer();
mod.eval(events, store, cache, {}, {}, deadline);
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::none);
EXPECT_EQ(events.size(), 0);
}
}

TEST(TestModule, BlockingRuleMatch)
{
std::vector<std::shared_ptr<core_rule>> rules;
{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(
std::make_shared<core_rule>("id1", "name", std::move(tags), builder.build()));
}

{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(std::make_shared<core_rule>("id2", "name", std::move(tags),
builder.build(), std::vector<std::string>{"block"}, true, core_rule::source_type::base,
core_rule::verdict_type::block));
}

rule_module_builder mod_builder{base_rule_precedence, null_grouping_key};
for (const auto &rule : rules) { mod_builder.insert(rule.get()); }

auto mod = mod_builder.build();

rule_module_cache cache;
mod.init_cache(cache);

ddwaf::object_store store;
{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.1"));

store.insert(root);

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::block);
EXPECT_EQ(events.size(), 1);
}

// No further calls should happen after a blocking rule matches
}

TEST(TestModule, MonitoringRuleMatch)
{
std::vector<std::shared_ptr<core_rule>> rules;
{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(
std::make_shared<core_rule>("id1", "name", std::move(tags), builder.build()));
}

{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.2"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(std::make_shared<core_rule>("id2", "name", std::move(tags),
builder.build(), std::vector<std::string>{"block"}, true, core_rule::source_type::base,
core_rule::verdict_type::block));
}

rule_module_builder mod_builder{base_rule_precedence, null_grouping_key};
for (const auto &rule : rules) { mod_builder.insert(rule.get()); }

auto mod = mod_builder.build();

rule_module_cache cache;
mod.init_cache(cache);

ddwaf::object_store store;
{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.1"));

store.insert(root);

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::monitor);
EXPECT_EQ(events.size(), 1);
}

// Check that we can still match the blocking rule
{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.2"));

store.insert(root);

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::block);
EXPECT_EQ(events.size(), 1);
}
}

TEST(TestModule, BlockingRuleMatchBasePrecedence)
{
std::vector<std::shared_ptr<core_rule>> rules;
{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(std::make_shared<core_rule>("id1", "name", std::move(tags),
builder.build(), std::vector<std::string>{"block"}, true, core_rule::source_type::user,
core_rule::verdict_type::block));
rules.emplace_back(
std::make_shared<core_rule>("id", "name", std::move(tags), builder.build()));
}

{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(std::make_shared<core_rule>("id2", "name", std::move(tags),
builder.build(), std::vector<std::string>{"block"}, true, core_rule::source_type::base,
core_rule::verdict_type::block));
}

rule_module_builder mod_builder{base_rule_precedence, null_grouping_key};
for (const auto &rule : rules) { mod_builder.insert(rule.get()); }

auto mod = mod_builder.build();

rule_module_cache cache;
mod.init_cache(cache);

ddwaf::object_store store;
{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.1"));

store.insert(root);

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::block);
EXPECT_EQ(events.size(), 1);
EXPECT_STRV(events[0].rule->get_id(), "id2");
}

// No further calls should happen after a blocking rule matches
}

TEST(TestModule, BlockingRuleMatchUserPrecedence)
{
std::vector<std::shared_ptr<core_rule>> rules;
{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(std::make_shared<core_rule>("id1", "name", std::move(tags),
builder.build(), std::vector<std::string>{"block"}, true, core_rule::source_type::user,
core_rule::verdict_type::block));
rules.emplace_back(
std::make_shared<core_rule>("id", "name", std::move(tags), builder.build()));
}

{
test::expression_builder builder(1);
builder.start_condition();
builder.add_argument();
builder.add_target("http.client_ip");
builder.end_condition<matcher::ip_match>(std::vector<std::string_view>{"192.168.0.1"});

std::unordered_map<std::string, std::string> tags{
{"type", "type"}, {"category", "category"}};

rules.emplace_back(std::make_shared<core_rule>("id2", "name", std::move(tags),
builder.build(), std::vector<std::string>{"block"}, true, core_rule::source_type::base,
core_rule::verdict_type::block));
}

rule_module_builder mod_builder{user_rule_precedence, null_grouping_key};
for (const auto &rule : rules) { mod_builder.insert(rule.get()); }

auto mod = mod_builder.build();

rule_module_cache cache;
mod.init_cache(cache);

ddwaf::object_store store;
{
ddwaf_object root;
ddwaf_object tmp;
ddwaf_object_map(&root);
ddwaf_object_map_add(&root, "http.client_ip", ddwaf_object_string(&tmp, "192.168.0.1"));

store.insert(root);

std::vector<event> events;
ddwaf::timer deadline = endless_timer();
auto verdict = mod.eval(events, store, cache, {}, {}, deadline);
EXPECT_EQ(verdict, rule_module::verdict_type::block);
EXPECT_EQ(events.size(), 1);
EXPECT_STRV(events[0].rule->get_id(), "id1");
}

// No further calls should happen after a blocking rule matches
}

TEST(TestModule, NonExpiringModule)
{
test::expression_builder builder(1);
Expand All @@ -84,6 +414,7 @@ TEST(TestModule, NonExpiringModule)
mod_builder.insert(rule.get());

auto mod = mod_builder.build();
EXPECT_FALSE(mod.may_expire());

rule_module_cache cache;
mod.init_cache(cache);
Expand All @@ -104,7 +435,6 @@ TEST(TestModule, NonExpiringModule)
EXPECT_EQ(events.size(), 1);
}
}

TEST(TestModule, ExpiringModule)
{
test::expression_builder builder(1);
Expand All @@ -122,6 +452,7 @@ TEST(TestModule, ExpiringModule)
mod_builder.insert(rule.get());

auto mod = mod_builder.build();
EXPECT_TRUE(mod.may_expire());

rule_module_cache cache;
mod.init_cache(cache);
Expand Down
Loading

0 comments on commit c01b719

Please sign in to comment.