new(userspace/falco,unit_tests): added new tests around schema validation feature.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
This commit is contained in:
parent
94dc7da986
commit
be927edfe8
|
|
@ -47,6 +47,7 @@ add_executable(falco_unit_tests
|
|||
falco/test_configuration_rule_selection.cpp
|
||||
falco/test_configuration_config_files.cpp
|
||||
falco/test_configuration_env_vars.cpp
|
||||
falco/test_configuration_schema.cpp
|
||||
falco/app/actions/test_select_event_sources.cpp
|
||||
falco/app/actions/test_load_config.cpp
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 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 <gtest/gtest.h>
|
||||
#include <falco/configuration.h>
|
||||
#include <falco_test_var.h>
|
||||
|
||||
#define EXPECT_VALIDATION_STATUS(res, status) \
|
||||
do { \
|
||||
for(const auto& pair : res) { \
|
||||
auto validation_status = pair.second; \
|
||||
EXPECT_TRUE(sinsp_utils::startswith(validation_status, status)); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
// Read Falco config from current repo-path
|
||||
TEST(Configuration, schema_validate_config)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_file(TEST_FALCO_CONFIG, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_ok)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
/* OK YAML */
|
||||
std::string config =
|
||||
"falco_libs:\n"
|
||||
" thread_table_size: 50\n";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_ok);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_wrong_key)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
/* Miss-typed key YAML */
|
||||
std::string config =
|
||||
"falco_libss:\n"
|
||||
" thread_table_size: 50\n";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_failed);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_wrong_type)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
|
||||
/* Wrong value type YAML */
|
||||
std::string config =
|
||||
"falco_libs: 512\n";
|
||||
|
||||
// We expect an exception since `falco_configuration::load_yaml()`
|
||||
// will fail to parse `falco_libs` node.
|
||||
ASSERT_ANY_THROW(falco_config.init_from_content(config, {}));
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_wrong_embedded_key)
|
||||
{
|
||||
falco_configuration falco_config;
|
||||
config_loaded_res res;
|
||||
|
||||
/* Miss-typed sub-key YAML */
|
||||
std::string config =
|
||||
"falco_libs:\n"
|
||||
" thread_table_sizeee: 50\n";
|
||||
|
||||
EXPECT_NO_THROW(res = falco_config.init_from_content(config, {}));
|
||||
EXPECT_VALIDATION_STATUS(res, yaml_helper::validation_failed);
|
||||
}
|
||||
|
||||
TEST(Configuration, schema_yaml_helper_validator)
|
||||
{
|
||||
yaml_helper conf;
|
||||
falco_configuration falco_config;
|
||||
|
||||
/* Broken YAML */
|
||||
std::string sample_yaml =
|
||||
"falco_libs:\n"
|
||||
" thread_table_size: 50\n";
|
||||
|
||||
// Ok, we don't ask for any validation
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml));
|
||||
|
||||
// We pass a string variable but not a schema
|
||||
std::string validation;
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml, Json::Value{}, &validation));
|
||||
EXPECT_EQ(validation, yaml_helper::validation_none);
|
||||
|
||||
// We pass a schema but not a string storage for the validation; no validation takes place
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml, falco_config.m_config_schema, nullptr));
|
||||
|
||||
// We pass everything
|
||||
EXPECT_NO_THROW(conf.load_from_string(sample_yaml, falco_config.m_config_schema, &validation));
|
||||
EXPECT_EQ(validation, yaml_helper::validation_ok);
|
||||
}
|
||||
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
#define TEST_ENGINE_KMOD_CONFIG "${CMAKE_SOURCE_DIR}/unit_tests/falco/test_configs/engine_kmod_config.yaml"
|
||||
#define TEST_ENGINE_MODERN_CONFIG "${CMAKE_SOURCE_DIR}/unit_tests/falco/test_configs/engine_modern_config.yaml"
|
||||
#define TEST_FALCO_CONFIG "${CMAKE_SOURCE_DIR}/falco.yaml"
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ falco::app::run_result falco::app::actions::load_config(const falco::app::state&
|
|||
{
|
||||
auto config_path = pair.first;
|
||||
auto validation = pair.second;
|
||||
auto priority = validation == "validated" ? falco_logger::level::INFO : falco_logger::level::WARNING;
|
||||
falco_logger::log(priority, std::string(" ") + config_path + " | " + validation + "\n");
|
||||
auto priority = validation == yaml_helper::validation_ok ? falco_logger::level::INFO : falco_logger::level::WARNING;
|
||||
falco_logger::log(priority, std::string(" ") + config_path + " | validation: " + validation + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -197,10 +197,9 @@ public:
|
|||
|
||||
// Needed by tests
|
||||
yaml_helper m_config;
|
||||
|
||||
private:
|
||||
Json::Value m_config_schema;
|
||||
|
||||
private:
|
||||
void merge_config_files(const std::string& config_name, config_loaded_res &res);
|
||||
void load_yaml(const std::string& config_name);
|
||||
void init_logger();
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ class yaml_helper
|
|||
{
|
||||
public:
|
||||
inline static const std::string configs_key = "config_files";
|
||||
inline static const std::string validation_ok = "ok";
|
||||
inline static const std::string validation_failed = "failed";
|
||||
inline static const std::string validation_none = "schema not provided";
|
||||
|
||||
/**
|
||||
* Load the YAML document represented by the input string.
|
||||
|
|
@ -102,7 +105,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
*validation = "no schema provided";
|
||||
*validation = validation_none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +219,7 @@ private:
|
|||
}
|
||||
else
|
||||
{
|
||||
*validation = "no schema provided";
|
||||
*validation = validation_none;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
|
|
@ -239,14 +242,14 @@ private:
|
|||
// report only the top-most error
|
||||
if (validationResults.popError(error))
|
||||
{
|
||||
return std::string("validation failed for ")
|
||||
return std::string(validation_failed + " for ")
|
||||
+ std::accumulate(error.context.begin(), error.context.end(), std::string(""))
|
||||
+ ": "
|
||||
+ error.description;
|
||||
}
|
||||
return "validation failed";
|
||||
return validation_failed;
|
||||
}
|
||||
return "validated";
|
||||
return validation_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue