diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e724613..22d63bfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,7 +214,6 @@ set(FALCO_BIN_DIR bin) add_subdirectory(scripts) add_subdirectory(userspace/engine) add_subdirectory(userspace/falco) -add_subdirectory(tests) if(NOT MUSL_OPTIMIZED_BUILD) include(plugins) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index 8818f91d..00000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright (C) 2019 The Falco Authors. -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. -# -set( - FALCO_TESTS_SOURCES - test_base.cpp - engine/test_rulesets.cpp - engine/test_falco_utils.cpp - engine/test_filter_macro_resolver.cpp - engine/test_filter_evttype_resolver.cpp - engine/test_filter_warning_resolver.cpp - engine/test_plugin_requirements.cpp - falco/test_yaml_helper.cpp -) - -set(FALCO_TESTED_LIBRARIES falco_engine ${YAMLCPP_LIB}) - -SET(FALCO_TESTS_ARGUMENTS "" CACHE STRING "Test arguments to pass to the Falco test suite") - -option(FALCO_BUILD_TESTS "Determines whether to build tests." ON) - -if(FALCO_BUILD_TESTS) - enable_testing() - if(NOT TARGET catch) - include(DownloadCatch) - endif() - - if(NOT TARGET fakeit) - include(DownloadFakeIt) - endif() - - add_executable(falco_test ${FALCO_TESTS_SOURCES}) - - target_link_libraries(falco_test PUBLIC ${FALCO_TESTED_LIBRARIES}) - - if(MINIMAL_BUILD) - target_include_directories( - falco_test - PUBLIC "${CATCH2_INCLUDE}" - "${FAKEIT_INCLUDE}" - "${PROJECT_SOURCE_DIR}/userspace/engine" - "${PROJECT_BINARY_DIR}/userspace/falco" - "${YAMLCPP_INCLUDE_DIR}" - "${PROJECT_SOURCE_DIR}/userspace/falco") - else() - target_include_directories( - falco_test - PUBLIC "${CATCH2_INCLUDE}" - "${FAKEIT_INCLUDE}" - "${PROJECT_SOURCE_DIR}/userspace/engine" - "${PROJECT_BINARY_DIR}/userspace/falco" - "${YAMLCPP_INCLUDE_DIR}" - "${PROJECT_SOURCE_DIR}/userspace/falco") - endif() - add_dependencies(falco_test catch2) - - include(CMakeParseArguments) - include(CTest) - include(Catch) - catch_discover_tests(falco_test) - separate_arguments(FALCO_TESTS_ARGUMENTS) - add_custom_target(tests COMMAND ${CMAKE_CTEST_COMMAND} ${FALCO_TESTS_ARGUMENTS} DEPENDS falco_test) -endif() diff --git a/tests/OWNERS b/tests/OWNERS deleted file mode 100644 index 15a5ddca..00000000 --- a/tests/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -labels: - - area/tests \ No newline at end of file diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index d89fdc3d..00000000 --- a/tests/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# Falco unit tests - -This folder contains the unit-tests suite for Falco. -The framework we use for unit-tests is [Catch2](https://github.com/catchorg/Catch2), while the one we use for mocking is [FakeIt](https://github.com/eranpeer/FakeIt). - - -## How to write tests - -When you want to test a new file or test a non tested file, remember four steps: - -- The folder structure here is the same as the one in the `userspace` folder, so `userspace/engine` becomes `tests/engine`. -- We call test files with this format `test_.cpp` -- Update the `CMakeLists.txt` file to include your file in `FALCO_TESTS_SOURCES` and change the `FALCO_TESTED_LIBRARIES` accordingly. You might also need to add dependencies, in that case, look at `target_link_libraries` and `target_include_directories` -- If you are unsure on how to write tests, refer to our existing tests in this folder and to the [Catch2](https://github.com/catchorg/Catch2/tree/master/docs) documentation. - -## How to execute tests - -The suite can be configured with `cmake` and run with `make`. - - -In the root folder of Falco, after creating the build directory: - -```bash -cd falco -mkdir build -cd build -``` - -You can prepare the tests with: - -``` -cmake .. -``` - -Optionally, you can customize the test suite by passing custom arguments like the examples below: - -**filter all tests containing the word ctor** - -```bash -cmake -DFALCO_TESTS_ARGUMENTS:STRING="-R ctor" .. -``` - -**verbose execution** - -```bash -cmake -DFALCO_TESTS_ARGUMENTS:STRING="-V" .. -``` - - -To see a list of all the custom arguments you may pass, execute `ctest --help` in your terminal. - - -Once you are ready, you can run your configuration with: - -```bash -make tests -``` diff --git a/tests/engine/test_falco_utils.cpp b/tests/engine/test_falco_utils.cpp deleted file mode 100644 index 55da4b0d..00000000 --- a/tests/engine/test_falco_utils.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright (C) 2020 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -#include "falco_utils.h" -#include - -TEST_CASE("is_unix_scheme matches", "[utils]") -{ - SECTION("rvalue") - { - bool res = falco::utils::network::is_unix_scheme("unix:///run/falco/falco.sock"); - REQUIRE(res); - } - - SECTION("std::string") - { - std::string url("unix:///run/falco/falco.sock"); - bool res = falco::utils::network::is_unix_scheme(url); - REQUIRE(res); - } - - SECTION("char[]") - { - char url[] = "unix:///run/falco/falco.sock"; - bool res = falco::utils::network::is_unix_scheme(url); - REQUIRE(res); - } -} - -TEST_CASE("is_unix_scheme does not match", "[utils]") -{ - bool res = falco::utils::network::is_unix_scheme("something:///run/falco/falco.sock"); - REQUIRE_FALSE(res); -} - -TEST_CASE("is_unix_scheme only matches scheme at the start of the string", "[utils]") -{ - bool res = falco::utils::network::is_unix_scheme("/var/run/unix:///falco.sock"); - REQUIRE_FALSE(res); -} diff --git a/tests/engine/test_filter_evttype_resolver.cpp b/tests/engine/test_filter_evttype_resolver.cpp deleted file mode 100644 index 534883bb..00000000 --- a/tests/engine/test_filter_evttype_resolver.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* -Copyright (C) 2021 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*/ - -#include "filter_evttype_resolver.h" -#include -#include -#include - -using namespace libsinsp::filter; - -std::string to_string(std::set s) -{ - std::string out = "["; - for(auto &val : s) - { - out += out.size() == 1 ? "" : ", "; - out += std::to_string(val); - } - out += "]"; - return out; -} - -void compare_evttypes(std::unique_ptr f, std::set &expected) -{ - std::set actual; - filter_evttype_resolver().evttypes(f.get(), actual); - for(auto &etype : expected) - { - REQUIRE(actual.find(etype) != actual.end()); - } - for(auto &etype : actual) - { - REQUIRE(expected.find(etype) != expected.end()); - } -} - -std::unique_ptr compile(const std::string &fltstr) -{ - return libsinsp::filter::parser(fltstr).parse(); -} - -TEST_CASE("Should find event types from filter", "[rule_loader]") -{ - std::set openat_only{ - PPME_SYSCALL_OPENAT_E, PPME_SYSCALL_OPENAT_X, - PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X }; - - std::set close_only{ - PPME_SYSCALL_CLOSE_E, PPME_SYSCALL_CLOSE_X }; - - std::set openat_close{ - PPME_SYSCALL_OPENAT_E, PPME_SYSCALL_OPENAT_X, - PPME_SYSCALL_OPENAT_2_E, PPME_SYSCALL_OPENAT_2_X, - PPME_SYSCALL_CLOSE_E, PPME_SYSCALL_CLOSE_X }; - - std::set not_openat; - std::set not_openat_close; - std::set not_close; - std::set all_events; - std::set no_events; - - for(uint32_t i = 2; i < PPM_EVENT_MAX; i++) - { - // Skip events that are unused. - if(sinsp::is_unused_event(i)) - { - continue; - } - - all_events.insert(i); - if(openat_only.find(i) == openat_only.end()) - { - not_openat.insert(i); - } - if(openat_close.find(i) == openat_close.end()) - { - not_openat_close.insert(i); - } - if (close_only.find(i) == close_only.end()) - { - not_close.insert(i); - } - } - - SECTION("evt_type_eq") - { - auto f = compile("evt.type=openat"); - compare_evttypes(std::move(f), openat_only); - } - - SECTION("evt_type_in") - { - auto f = compile("evt.type in (openat, close)"); - compare_evttypes(std::move(f), openat_close); - } - - SECTION("evt_type_ne") - { - auto f = compile("evt.type!=openat"); - compare_evttypes(std::move(f), not_openat); - } - - SECTION("not_evt_type_eq") - { - auto f = compile("not evt.type=openat"); - compare_evttypes(std::move(f), not_openat); - } - - SECTION("not_evt_type_in") - { - auto f = compile("not evt.type in (openat, close)"); - compare_evttypes(std::move(f), not_openat_close); - } - - SECTION("not_evt_type_ne") - { - auto f = compile("not evt.type != openat"); - compare_evttypes(std::move(f), openat_only); - } - - SECTION("evt_type_or") - { - auto f = compile("evt.type=openat or evt.type=close"); - compare_evttypes(std::move(f), openat_close); - } - - SECTION("not_evt_type_or") - { - auto f = compile("evt.type!=openat or evt.type!=close"); - compare_evttypes(std::move(f), all_events); - } - - SECTION("evt_type_or_ne") - { - auto f = compile("evt.type=close or evt.type!=openat"); - compare_evttypes(std::move(f), not_openat); - } - - SECTION("evt_type_and") - { - auto f = compile("evt.type=close and evt.type=openat"); - compare_evttypes(std::move(f), no_events); - } - - SECTION("evt_type_and_non_evt_type") - { - auto f = compile("evt.type=openat and proc.name=nginx"); - compare_evttypes(std::move(f), openat_only); - } - - SECTION("evt_type_and_non_evt_type_not") - { - auto f = compile("evt.type=openat and not proc.name=nginx"); - compare_evttypes(std::move(f), openat_only); - } - - SECTION("evt_type_and_nested") - { - auto f = compile("evt.type=openat and (proc.name=nginx)"); - compare_evttypes(std::move(f), openat_only); - } - - SECTION("evt_type_and_nested_multi") - { - auto f = compile("evt.type=openat and (evt.type=close and proc.name=nginx)"); - compare_evttypes(std::move(f), no_events); - } - - SECTION("non_evt_type") - { - auto f = compile("proc.name=nginx"); - compare_evttypes(std::move(f), all_events); - } - - SECTION("non_evt_type_or") - { - auto f = compile("evt.type=openat or proc.name=nginx"); - compare_evttypes(std::move(f), all_events); - } - - SECTION("non_evt_type_or_nested_first") - { - auto f = compile("(evt.type=openat) or proc.name=nginx"); - compare_evttypes(std::move(f), all_events); - } - - SECTION("non_evt_type_or_nested_second") - { - auto f = compile("evt.type=openat or (proc.name=nginx)"); - compare_evttypes(std::move(f), all_events); - } - - SECTION("non_evt_type_or_nested_multi") - { - auto f = compile("evt.type=openat or (evt.type=close and proc.name=nginx)"); - compare_evttypes(std::move(f), openat_close); - } - - SECTION("non_evt_type_or_nested_multi_not") - { - auto f = compile("evt.type=openat or not (evt.type=close and proc.name=nginx)"); - compare_evttypes(std::move(f), not_close); - } - - SECTION("non_evt_type_and_nested_multi_not") - { - auto f = compile("evt.type=openat and not (evt.type=close and proc.name=nginx)"); - compare_evttypes(std::move(f), openat_only); - } - - SECTION("ne_and_and") - { - auto f = compile("evt.type!=openat and evt.type!=close"); - compare_evttypes(std::move(f), not_openat_close); - } - - SECTION("not_not") - { - auto f = compile("not (not evt.type=openat)"); - compare_evttypes(std::move(f), openat_only); - } -} diff --git a/tests/engine/test_filter_macro_resolver.cpp b/tests/engine/test_filter_macro_resolver.cpp deleted file mode 100644 index 63b2083c..00000000 --- a/tests/engine/test_filter_macro_resolver.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* -Copyright (C) 2020 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include "filter_macro_resolver.h" -#include - -using namespace libsinsp::filter::ast; - -static std::vector::const_iterator find_value( - const std::vector& values, - const std::string& ref) -{ - return std::find_if( - values.begin(), - values.end(), - [&ref](const filter_macro_resolver::value_info& v) { return v.first == ref; }); -} - -TEST_CASE("Should resolve macros on a filter AST", "[rule_loader]") -{ - std::string macro_name = "test_macro"; - pos_info macro_pos(12, 85, 27); - - SECTION("in the general case") - { - std::shared_ptr macro = std::move( - unary_check_expr::create("test.field", "", "exists")); - - std::vector> filter_and; - filter_and.push_back(unary_check_expr::create("evt.name", "", "exists")); - filter_and.push_back(not_expr::create(value_expr::create(macro_name, macro_pos))); - std::shared_ptr filter = std::move(and_expr::create(filter_and)); - - std::vector> expected_and; - expected_and.push_back(unary_check_expr::create("evt.name", "", "exists")); - expected_and.push_back(not_expr::create(clone(macro.get()))); - std::shared_ptr expected = std::move(and_expr::create(expected_and)); - - filter_macro_resolver resolver; - resolver.set_macro(macro_name, macro); - - // first run - REQUIRE(resolver.run(filter) == true); - REQUIRE(resolver.get_resolved_macros().size() == 1); - REQUIRE(resolver.get_resolved_macros().begin()->first == macro_name); - REQUIRE(resolver.get_resolved_macros().begin()->second == macro_pos); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(expected.get())); - - // second run - REQUIRE(resolver.run(filter) == false); - REQUIRE(resolver.get_resolved_macros().empty()); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(expected.get())); - } - - SECTION("with a single node") - { - std::shared_ptr macro = std::move( - unary_check_expr::create("test.field", "", "exists")); - - std::shared_ptr filter = std::move(value_expr::create(macro_name, macro_pos)); - - filter_macro_resolver resolver; - resolver.set_macro(macro_name, macro); - - // first run - expr* old_filter_ptr = filter.get(); - REQUIRE(resolver.run(filter) == true); - REQUIRE(filter.get() != old_filter_ptr); - REQUIRE(resolver.get_resolved_macros().size() == 1); - REQUIRE(resolver.get_resolved_macros().begin()->first == macro_name); - REQUIRE(resolver.get_resolved_macros().begin()->second == macro_pos); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(macro.get())); - - // second run - old_filter_ptr = filter.get(); - REQUIRE(resolver.run(filter) == false); - REQUIRE(filter.get() == old_filter_ptr); - REQUIRE(resolver.get_resolved_macros().empty()); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(macro.get())); - } - - SECTION("with multiple macros") - { - std::string a_macro_name = macro_name + "_1"; - std::string b_macro_name = macro_name + "_2"; - - pos_info a_macro_pos(11, 75, 43); - pos_info b_macro_pos(91, 21, 9); - - std::shared_ptr a_macro = std::move( - unary_check_expr::create("one.field", "", "exists")); - std::shared_ptr b_macro = std::move( - unary_check_expr::create("another.field", "", "exists")); - - std::vector> filter_or; - filter_or.push_back(value_expr::create(a_macro_name, a_macro_pos)); - filter_or.push_back(value_expr::create(b_macro_name, b_macro_pos)); - std::shared_ptr filter = std::move(or_expr::create(filter_or)); - - std::vector> expected_or; - expected_or.push_back(clone(a_macro.get())); - expected_or.push_back(clone(b_macro.get())); - std::shared_ptr expected_filter = std::move(or_expr::create(expected_or)); - - filter_macro_resolver resolver; - resolver.set_macro(a_macro_name, a_macro); - resolver.set_macro(b_macro_name, b_macro); - - // first run - REQUIRE(resolver.run(filter) == true); - REQUIRE(resolver.get_resolved_macros().size() == 2); - auto a_resolved_itr = find_value(resolver.get_resolved_macros(), a_macro_name); - REQUIRE(a_resolved_itr != resolver.get_resolved_macros().end()); - REQUIRE(a_resolved_itr->first == a_macro_name); - REQUIRE(a_resolved_itr->second == a_macro_pos); - - auto b_resolved_itr = find_value(resolver.get_resolved_macros(), b_macro_name); - REQUIRE(b_resolved_itr != resolver.get_resolved_macros().end()); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(b_resolved_itr->first == b_macro_name); - REQUIRE(b_resolved_itr->second == b_macro_pos); - REQUIRE(filter->is_equal(expected_filter.get())); - - // second run - REQUIRE(resolver.run(filter) == false); - REQUIRE(resolver.get_resolved_macros().empty()); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(expected_filter.get())); - } - - SECTION("with nested macros") - { - std::string a_macro_name = macro_name + "_1"; - std::string b_macro_name = macro_name + "_2"; - - pos_info a_macro_pos(47, 1, 76); - pos_info b_macro_pos(111, 65, 2); - - std::vector> a_macro_and; - a_macro_and.push_back(unary_check_expr::create("one.field", "", "exists")); - a_macro_and.push_back(value_expr::create(b_macro_name, b_macro_pos)); - std::shared_ptr a_macro = std::move(and_expr::create(a_macro_and)); - - std::shared_ptr b_macro = std::move( - unary_check_expr::create("another.field", "", "exists")); - - std::shared_ptr filter = std::move(value_expr::create(a_macro_name, a_macro_pos)); - - std::vector> expected_and; - expected_and.push_back(unary_check_expr::create("one.field", "", "exists")); - expected_and.push_back(unary_check_expr::create("another.field", "", "exists")); - std::shared_ptr expected_filter = std::move(and_expr::create(expected_and)); - - filter_macro_resolver resolver; - resolver.set_macro(a_macro_name, a_macro); - resolver.set_macro(b_macro_name, b_macro); - - // first run - REQUIRE(resolver.run(filter) == true); - REQUIRE(resolver.get_resolved_macros().size() == 2); - auto a_resolved_itr = find_value(resolver.get_resolved_macros(), a_macro_name); - REQUIRE(a_resolved_itr != resolver.get_resolved_macros().end()); - REQUIRE(a_resolved_itr->first == a_macro_name); - REQUIRE(a_resolved_itr->second == a_macro_pos); - - auto b_resolved_itr = find_value(resolver.get_resolved_macros(), b_macro_name); - REQUIRE(b_resolved_itr != resolver.get_resolved_macros().end()); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(b_resolved_itr->first == b_macro_name); - REQUIRE(b_resolved_itr->second == b_macro_pos); - - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(expected_filter.get())); - - // second run - REQUIRE(resolver.run(filter) == false); - REQUIRE(resolver.get_resolved_macros().empty()); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(expected_filter.get())); - } -} - -TEST_CASE("Should find unknown macros", "[rule_loader]") -{ - std::string macro_name = "test_macro"; - pos_info macro_pos(9, 4, 2); - - SECTION("in the general case") - { - std::vector> filter_and; - filter_and.push_back(unary_check_expr::create("evt.name", "", "exists")); - filter_and.push_back(not_expr::create(value_expr::create(macro_name, macro_pos))); - std::shared_ptr filter = std::move(and_expr::create(filter_and)); - - filter_macro_resolver resolver; - REQUIRE(resolver.run(filter) == false); - REQUIRE(resolver.get_unknown_macros().size() == 1); - REQUIRE(resolver.get_unknown_macros().begin()->first == macro_name); - REQUIRE(resolver.get_unknown_macros().begin()->second == macro_pos); - REQUIRE(resolver.get_resolved_macros().empty()); - } - - SECTION("with nested macros") - { - std::string a_macro_name = macro_name + "_1"; - std::string b_macro_name = macro_name + "_2"; - - pos_info a_macro_pos(32, 84, 9); - pos_info b_macro_pos(1, 0, 5); - - std::vector> a_macro_and; - a_macro_and.push_back(unary_check_expr::create("one.field", "", "exists")); - a_macro_and.push_back(value_expr::create(b_macro_name, b_macro_pos)); - std::shared_ptr a_macro = std::move(and_expr::create(a_macro_and)); - - std::shared_ptr filter = std::move(value_expr::create(a_macro_name, a_macro_pos)); - auto expected_filter = clone(a_macro.get()); - - filter_macro_resolver resolver; - resolver.set_macro(a_macro_name, a_macro); - - // first run - REQUIRE(resolver.run(filter) == true); - REQUIRE(resolver.get_resolved_macros().size() == 1); - REQUIRE(resolver.get_resolved_macros().begin()->first == a_macro_name); - REQUIRE(resolver.get_resolved_macros().begin()->second == a_macro_pos); - REQUIRE(resolver.get_unknown_macros().size() == 1); - REQUIRE(resolver.get_unknown_macros().begin()->first == b_macro_name); - REQUIRE(resolver.get_unknown_macros().begin()->second == b_macro_pos); - REQUIRE(filter->is_equal(expected_filter.get())); - } -} - -TEST_CASE("Should undefine macro", "[rule_loader]") -{ - std::string macro_name = "test_macro"; - pos_info macro_pos_1(12, 9, 3); - pos_info macro_pos_2(9, 6, 3); - - std::shared_ptr macro = std::move(unary_check_expr::create("test.field", "", "exists")); - std::shared_ptr a_filter = std::move(value_expr::create(macro_name, macro_pos_1)); - std::shared_ptr b_filter = std::move(value_expr::create(macro_name, macro_pos_2)); - filter_macro_resolver resolver; - - resolver.set_macro(macro_name, macro); - REQUIRE(resolver.run(a_filter) == true); - REQUIRE(resolver.get_resolved_macros().size() == 1); - REQUIRE(resolver.get_resolved_macros().begin()->first == macro_name); - REQUIRE(resolver.get_resolved_macros().begin()->second == macro_pos_1); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(a_filter->is_equal(macro.get())); - - resolver.set_macro(macro_name, NULL); - REQUIRE(resolver.run(b_filter) == false); - REQUIRE(resolver.get_resolved_macros().empty()); - REQUIRE(resolver.get_unknown_macros().size() == 1); - REQUIRE(resolver.get_unknown_macros().begin()->first == macro_name); - REQUIRE(resolver.get_unknown_macros().begin()->second == macro_pos_2); -} - -// checks that the macro AST is cloned and not shared across resolved filters -TEST_CASE("Should clone macro AST", "[rule_loader]") -{ - std::string macro_name = "test_macro"; - pos_info macro_pos(5, 2, 8888); - std::shared_ptr macro = std::move(unary_check_expr::create("test.field", "", "exists")); - std::shared_ptr filter = std::move(value_expr::create(macro_name, macro_pos)); - filter_macro_resolver resolver; - - resolver.set_macro(macro_name, macro); - REQUIRE(resolver.run(filter) == true); - REQUIRE(resolver.get_resolved_macros().size() == 1); - REQUIRE(resolver.get_resolved_macros().begin()->first == macro_name); - REQUIRE(resolver.get_resolved_macros().begin()->second == macro_pos); - REQUIRE(resolver.get_unknown_macros().empty()); - REQUIRE(filter->is_equal(macro.get())); - - macro->field = "another.field"; - REQUIRE(!filter->is_equal(macro.get())); -} diff --git a/tests/engine/test_filter_warning_resolver.cpp b/tests/engine/test_filter_warning_resolver.cpp deleted file mode 100644 index da2b874d..00000000 --- a/tests/engine/test_filter_warning_resolver.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright (C) 2020 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include "filter_warning_resolver.h" -#include - -static bool warns(const std::string& condition) -{ - std::set w; - auto ast = libsinsp::filter::parser(condition).parse(); - filter_warning_resolver().run(ast.get(), w); - return !w.empty(); -} - -TEST_CASE("Should spot warnings in filtering conditions", "[rule_loader]") -{ - SECTION("for unsafe usage of in k8s audit fields") - { - REQUIRE(false == warns("ka.field exists")); - REQUIRE(false == warns("some.field = ")); - REQUIRE(true == warns("jevt.field = ")); - REQUIRE(true == warns("ka.field = ")); - REQUIRE(true == warns("ka.field == ")); - REQUIRE(true == warns("ka.field != ")); - REQUIRE(true == warns("ka.field in ()")); - REQUIRE(true == warns("ka.field in (otherval, )")); - REQUIRE(true == warns("ka.field intersects ()")); - REQUIRE(true == warns("ka.field intersects (otherval, )")); - REQUIRE(true == warns("ka.field pmatch ()")); - REQUIRE(true == warns("ka.field pmatch (otherval, )")); - } -} diff --git a/tests/engine/test_plugin_requirements.cpp b/tests/engine/test_plugin_requirements.cpp deleted file mode 100644 index c3ce2de9..00000000 --- a/tests/engine/test_plugin_requirements.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* -Copyright (C) 2022 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include -#include -#include "falco_engine.h" - -static void check_requirements( - bool expect_success, - const std::vector& plugins, - const std::string& ruleset_content) -{ - std::string err; - std::unique_ptr e(new falco_engine()); - falco::load_result::rules_contents_t c = {{"test", ruleset_content}}; - - auto res = e->load_rules(c.begin()->second, c.begin()->first); - if (!res->successful()) - { - if (expect_success) - { - FAIL(res->as_string(false, c)); - } - return; - } - - if (!e->check_plugin_requirements(plugins, err)) - { - if (expect_success) - { - FAIL(err); - } - } - else if (!expect_success) - { - FAIL("unexpected successful plugin requirements check"); - } -} - -TEST_CASE("check_plugin_requirements must accept", "[rule_loader]") -{ - SECTION("no requirement") - { - check_requirements(true, {{"k8saudit", "0.1.0"}}, ""); - } - - SECTION("single plugin") - { - check_requirements(true, {{"k8saudit", "0.1.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - )"); - } - - SECTION("single plugin newer version") - { - check_requirements(true, {{"k8saudit", "0.2.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - )"); - } - - SECTION("multiple plugins") - { - check_requirements(true, {{"k8saudit", "0.1.0"}, {"json", "0.3.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - - name: json - version: 0.3.0 - )"); - } - - SECTION("single plugin multiple versions") - { - check_requirements(true, {{"k8saudit", "0.2.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 -- required_plugin_versions: - - name: k8saudit - version: 0.2.0 - )"); - } - - SECTION("single plugin with alternatives") - { - check_requirements(true, {{"k8saudit-other", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - alternatives: - - name: k8saudit-other - version: 0.4.0 - )"); - } - - SECTION("multiple plugins with alternatives") - { - check_requirements(true, {{"k8saudit-other", "0.5.0"}, {"json2", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - alternatives: - - name: k8saudit-other - version: 0.4.0 - - name: json - version: 0.3.0 - alternatives: - - name: json2 - version: 0.1.0 - )"); - } - - SECTION("multiple plugins with alternatives with multiple versions") - { - check_requirements(true, {{"k8saudit-other", "0.7.0"}, {"json2", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - alternatives: - - name: k8saudit-other - version: 0.4.0 - - name: json - version: 0.3.0 - alternatives: - - name: json2 - version: 0.1.0 -- required_plugin_versions: - - name: k8saudit - version: 1.0.0 - alternatives: - - name: k8saudit-other - version: 0.7.0 - )"); - } -} - -TEST_CASE("check_plugin_requirements must reject", "[rule_loader]") -{ - SECTION("no plugin loaded") - { - check_requirements(false, {}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - )"); - } - - SECTION("single plugin wrong name") - { - check_requirements(false, {{"k8saudit", "0.1.0"}}, R"( -- required_plugin_versions: - - name: k8saudit2 - version: 0.1.0 - )"); - } - - SECTION("single plugin wrong version") - { - check_requirements(false, {{"k8saudit", "0.1.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.2.0 - )"); - } - - SECTION("multiple plugins") - { - check_requirements(false, {{"k8saudit", "0.1.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - - name: json - version: 0.3.0 - )"); - } - - SECTION("single plugin multiple versions") - { - check_requirements(false, {{"k8saudit", "0.1.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 -- required_plugin_versions: - - name: k8saudit - version: 0.2.0 - )"); - } - - SECTION("single plugin with alternatives") - { - check_requirements(false, {{"k8saudit2", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - alternatives: - - name: k8saudit-other - version: 0.4.0 - )"); - } - - SECTION("single plugin with overlapping alternatives") - { - check_requirements(false, {{"k8saudit", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - alternatives: - - name: k8saudit - version: 0.4.0 - )"); - } - - SECTION("multiple plugins with alternatives") - { - check_requirements(false, {{"k8saudit-other", "0.5.0"}, {"json3", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.1.0 - alternatives: - - name: k8saudit-other - version: 0.4.0 - - name: json - version: 0.3.0 - alternatives: - - name: json2 - version: 0.1.0 - )"); - } - - SECTION("multiple plugins with alternatives with multiple versions") - { - check_requirements(false, {{"k8saudit", "0.7.0"}, {"json2", "0.5.0"}}, R"( -- required_plugin_versions: - - name: k8saudit - version: 0.4.0 - alternatives: - - name: k8saudit-other - version: 0.4.0 - - name: json - version: 0.3.0 - alternatives: - - name: json2 - version: 0.1.0 -- required_plugin_versions: - - name: k8saudit - version: 1.0.0 - alternatives: - - name: k8saudit-other - version: 0.7.0 - )"); - } -} diff --git a/tests/engine/test_rulesets.cpp b/tests/engine/test_rulesets.cpp deleted file mode 100644 index 0f45f7e6..00000000 --- a/tests/engine/test_rulesets.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* -Copyright (C) 2020 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include "falco_common.h" -#include "evttype_index_ruleset.h" -#include -#include - -static bool exact_match = true; -static bool substring_match = false; -static uint16_t default_ruleset = 0; -static uint16_t non_default_ruleset = 3; -static uint16_t other_non_default_ruleset = 2; -static std::set tags = {"some_tag", "some_other_tag"}; -static std::set evttypes = { ppm_event_type::PPME_GENERIC_E }; - -static std::shared_ptr create_factory() -{ - std::shared_ptr ret(new sinsp_filter_factory(NULL)); - - return ret; -} - -static std::shared_ptr create_ast( - std::shared_ptr f) -{ - libsinsp::filter::parser parser("evt.type=open"); - std::shared_ptr ret(parser.parse()); - - return ret; -} - -static std::shared_ptr create_filter( - std::shared_ptr f, - std::shared_ptr ast) -{ - sinsp_filter_compiler compiler(f, ast.get()); - std::shared_ptr filter(compiler.compile()); - - return filter; -} - -static std::shared_ptr create_ruleset( - std::shared_ptr f) -{ - std::shared_ptr ret(new evttype_index_ruleset(f)); - return ret; -} - -TEST_CASE("Should enable/disable on ruleset", "[rulesets]") -{ - auto f = create_factory(); - auto r = create_ruleset(f); - auto ast = create_ast(f); - auto filter = create_filter(f, ast); - falco_rule rule; - rule.name = "one_rule"; - rule.source = falco_common::syscall_source; - rule.tags = tags; - - r->add(rule, filter, ast); - - SECTION("Should enable/disable for exact match w/ default ruleset") - { - r->enable("one_rule", exact_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable("one_rule", exact_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for exact match w/ specific ruleset") - { - r->enable("one_rule", exact_match, non_default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 1); - REQUIRE(r->enabled_count(default_ruleset) == 0); - REQUIRE(r->enabled_count(other_non_default_ruleset) == 0); - - r->disable("one_rule", exact_match, non_default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 0); - REQUIRE(r->enabled_count(default_ruleset) == 0); - REQUIRE(r->enabled_count(other_non_default_ruleset) == 0); - } - - SECTION("Should not enable for exact match different rule name") - { - r->enable("some_other_rule", exact_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for exact match w/ substring and default ruleset") - { - r->enable("one_rule", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable("one_rule", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should not enable for substring w/ exact_match") - { - r->enable("one_", exact_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for prefix match w/ default ruleset") - { - r->enable("one_", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable("one_", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for suffix match w/ default ruleset") - { - r->enable("_rule", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable("_rule", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for substring match w/ default ruleset") - { - r->enable("ne_ru", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable("ne_ru", substring_match, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for substring match w/ specific ruleset") - { - r->enable("ne_ru", substring_match, non_default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 1); - REQUIRE(r->enabled_count(default_ruleset) == 0); - REQUIRE(r->enabled_count(other_non_default_ruleset) == 0); - - r->disable("ne_ru", substring_match, non_default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 0); - REQUIRE(r->enabled_count(default_ruleset) == 0); - REQUIRE(r->enabled_count(other_non_default_ruleset) == 0); - } - - SECTION("Should enable/disable for tags w/ default ruleset") - { - std::set want_tags = {"some_tag"}; - - r->enable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - - SECTION("Should enable/disable for tags w/ specific ruleset") - { - std::set want_tags = {"some_tag"}; - - r->enable_tags(want_tags, non_default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 1); - REQUIRE(r->enabled_count(default_ruleset) == 0); - REQUIRE(r->enabled_count(other_non_default_ruleset) == 0); - - r->disable_tags(want_tags, non_default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 0); - REQUIRE(r->enabled_count(default_ruleset) == 0); - REQUIRE(r->enabled_count(other_non_default_ruleset) == 0); - } - - SECTION("Should not enable for different tags") - { - std::set want_tags = {"some_different_tag"}; - - r->enable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(non_default_ruleset) == 0); - } - - SECTION("Should enable/disable for overlapping tags") - { - std::set want_tags = {"some_tag", "some_different_tag"}; - - r->enable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - r->disable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); - } - -} - -TEST_CASE("Should enable/disable on ruleset for incremental adding tags", "[rulesets]") -{ - auto f = create_factory(); - auto r = create_ruleset(f); - auto ast = create_ast(f); - - auto rule1_filter = create_filter(f, ast); - falco_rule rule1; - rule1.name = "one_rule"; - rule1.source = falco_common::syscall_source; - rule1.tags = {"rule1_tag"}; - r->add(rule1, rule1_filter, ast); - - auto rule2_filter = create_filter(f, ast); - falco_rule rule2; - rule2.name = "two_rule"; - rule2.source = falco_common::syscall_source; - rule2.tags = {"rule2_tag"}; - r->add(rule2, rule2_filter, ast); - - std::set want_tags; - - want_tags = rule1.tags; - r->enable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - want_tags = rule2.tags; - r->enable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 2); - - r->disable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 1); - - want_tags = rule1.tags; - r->disable_tags(want_tags, default_ruleset); - REQUIRE(r->enabled_count(default_ruleset) == 0); -} diff --git a/tests/falco/test_yaml_helper.cpp b/tests/falco/test_yaml_helper.cpp deleted file mode 100644 index 02be7c73..00000000 --- a/tests/falco/test_yaml_helper.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright (C) 2021 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -#include "configuration.h" -#include - -std::string sample_yaml = - "base_value:\n" - " id: 1\n" - " name: 'sample_name'\n" - " subvalue:\n" - " subvalue2:\n" - " boolean: true\n" - "base_value_2:\n" - " sample_list:\n" - " - elem1\n" - " - elem2\n" - " - elem3\n" -; - -TEST_CASE("configuration must load YAML data", "[configuration]") -{ - yaml_helper conf; - - SECTION("broken YAML") - { - std::string sample_broken_yaml = sample_yaml + " / bad_symbol"; - REQUIRE_THROWS(conf.load_from_string(sample_broken_yaml)); - } - - SECTION("valid YAML") - { - REQUIRE_NOTHROW(conf.load_from_string(sample_yaml)); - } - - SECTION("clearing and reloading") - { - conf.load_from_string(sample_yaml); - REQUIRE(conf.is_defined("base_value") == true); - conf.clear(); - REQUIRE(conf.is_defined("base_value") == false); - conf.load_from_string(sample_yaml); - REQUIRE(conf.is_defined("base_value") == true); - } -} - -TEST_CASE("configuration must read YAML fields", "[configuration]") -{ - yaml_helper conf; - conf.load_from_string(sample_yaml); - - SECTION("base level") - { - REQUIRE(conf.is_defined("base_value") == true); - REQUIRE(conf.is_defined("base_value_2") == true); - REQUIRE(conf.is_defined("unknown_base_value") == false); - } - - SECTION("arbitrary depth nesting") - { - REQUIRE(conf.get_scalar("base_value.id", -1) == 1); - REQUIRE(conf.get_scalar("base_value.name", "none") == "sample_name"); - REQUIRE(conf.get_scalar("base_value.subvalue.subvalue2.boolean", false) == true); - } - - SECTION("list field elements") - { - REQUIRE(conf.get_scalar("base_value_2.sample_list[0]", "none") == "elem1"); - REQUIRE(conf.get_scalar("base_value_2.sample_list[1]", "none") == "elem2"); - REQUIRE(conf.get_scalar("base_value_2.sample_list[2]", "none") == "elem3"); - } - - SECTION("sequence") - { - std::vector seq; - conf.get_sequence(seq, "base_value_2.sample_list"); - REQUIRE(seq.size() == 3); - REQUIRE(seq[0] == "elem1"); - REQUIRE(seq[1] == "elem2"); - REQUIRE(seq[2] == "elem3"); - } -} - -TEST_CASE("configuration must modify YAML fields", "[configuration]") -{ - std::string key = "base_value.subvalue.subvalue2.boolean"; - yaml_helper conf; - conf.load_from_string(sample_yaml); - REQUIRE(conf.get_scalar(key, false) == true); - conf.set_scalar(key, false); - REQUIRE(conf.get_scalar(key, true) == false); - conf.set_scalar(key, true); - REQUIRE(conf.get_scalar(key, false) == true); -} diff --git a/tests/test_base.cpp b/tests/test_base.cpp deleted file mode 100644 index 0359948f..00000000 --- a/tests/test_base.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright (C) 2019 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -#define CATCH_CONFIG_MAIN -#define CATCH_CONFIG_CONSOLE_WIDTH 300 -#include - -TEST_CASE("all test cases reside in other .cpp files (empty)", "[multi-file:1]") -{ -}