Skip to content

Commit

Permalink
fix agent test memory corruption, add drive_size ut
Browse files Browse the repository at this point in the history
  • Loading branch information
jean-christophe81 committed Nov 14, 2024
1 parent c69da16 commit e277e51
Show file tree
Hide file tree
Showing 12 changed files with 714 additions and 69 deletions.
39 changes: 32 additions & 7 deletions agent/inc/com/centreon/agent/drive_size.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cstdint>
#include <memory>
#include "absl/base/thread_annotations.h"
#include "absl/container/btree_set.h"
#include "absl/synchronization/mutex.h"
#include "boost/asio/io_context.hpp"
#include "check.hh"
Expand Down Expand Up @@ -109,18 +110,37 @@ class filter {
struct fs_stat {
fs_stat() = default;
fs_stat(std::string&& fs_in, uint64_t used_in, uint64_t total_in)
: fs(fs_in), used(used_in), total(total_in) {}
: fs(fs_in), mount_point(fs), used(used_in), total(total_in) {}

fs_stat(std::string&& fs_in,
std::string&& mount_point_in,
uint64_t used_in,
uint64_t total_in)
: fs(fs_in),
mount_point(mount_point_in),
used(used_in),
total(total_in) {}

fs_stat(const std::string_view& fs_in,
const std::string_view& mount_point_in,
uint64_t used_in,
uint64_t total_in)
: fs(fs_in),
mount_point(mount_point_in),
used(used_in),
total(total_in) {}

std::string fs;
std::string mount_point;
uint64_t used;
uint64_t total;

bool is_used_more_than_threshold(uint64_t threshold) const {
return used >= threshold;
}

bool is_free_more_than_threshold(uint64_t threshold) const {
return total - used >= threshold;
bool is_free_less_than_threshold(uint64_t threshold) const {
return total - used < threshold;
}

bool is_used_more_than_prct_threshold(uint64_t percent_hundredth) const {
Expand All @@ -130,11 +150,11 @@ struct fs_stat {
return (used * 10000) / total >= percent_hundredth;
}

bool is_free_more_than_prct_threshold(uint64_t percent_hundredth) const {
bool is_free_less_than_prct_threshold(uint64_t percent_hundredth) const {
if (!total) {
return true;
}
return ((total - used) * 10000) / total >= percent_hundredth;
return ((total - used) * 10000) / total < percent_hundredth;
}

double get_used_prct() const {
Expand Down Expand Up @@ -182,8 +202,9 @@ class drive_size_thread

static get_fs_stats os_fs_stats;

drive_size_thread(const std::shared_ptr<spdlog::logger>& logger)
: _logger(logger) {}
drive_size_thread(const std::shared_ptr<asio::io_context>& io_context,
const std::shared_ptr<spdlog::logger>& logger)
: _io_context(io_context), _logger(logger) {}

void run();

Expand All @@ -197,6 +218,10 @@ class drive_size_thread

} // namespace check_drive_size_detail

/**
* @brief drive size check object (same for linux and windows)
*
*/
class check_drive_size : public check {
std::shared_ptr<check_drive_size_detail::filter> _filter;
bool _prct_threshold;
Expand Down
4 changes: 4 additions & 0 deletions agent/native_windows/src/check_drive_size.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ std::list<fs_stat> os_fs_stats(filter& filt,
&total_number_of_free_bytes);

if (success) {
SPDLOG_LOGGER_TRACE(logger, "{} total: {}, free {}", fs_to_test,
total_number_of_bytes.QuadPart ,
total_number_of_free_bytes.QuadPart);

result.emplace_back(std::move(fs_to_test),
total_number_of_bytes.QuadPart -
total_number_of_free_bytes.QuadPart,
Expand Down
41 changes: 24 additions & 17 deletions agent/src/drive_size.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ filter::filter(const rapidjson::Value& args) : _fs_type_filter(0xFFFFFFFFU) {
throw exceptions::msg_fmt("invalid regex for filter-storage-type: {}",
member_iter->value.GetString());
}

_fs_type_filter = 0;
for (const auto& [label, flag] : _fs_type) {
if (RE2::FullMatch(label, filter_typ_re)) {
_fs_type_filter |= flag;
Expand All @@ -115,7 +115,7 @@ filter::filter(const rapidjson::Value& args) : _fs_type_filter(0xFFFFFFFFU) {
throw exceptions::msg_fmt("invalid regex for filter-fs: {}",
member_iter->value.GetString());
}
} else if (member_iter->name == "filter-exclude-fs") {
} else if (member_iter->name == "exclude-fs") {
_filter_exclude_fs =
std::make_unique<re2::RE2>(member_iter->value.GetString());
if (!_filter_exclude_fs->ok()) { // NOLINT
Expand All @@ -129,7 +129,7 @@ filter::filter(const rapidjson::Value& args) : _fs_type_filter(0xFFFFFFFFU) {
throw exceptions::msg_fmt("invalid regex for filter-mountpoint: {}",
member_iter->value.GetString());
}
} else if (member_iter->name == "filter-exclude-mountpoint") {
} else if (member_iter->name == "exclude-mountpoint") {
_filter_exclude_mountpoint =
std::make_unique<re2::RE2>(member_iter->value.GetString());
if (!_filter_exclude_mountpoint->ok()) {
Expand Down Expand Up @@ -261,20 +261,23 @@ void drive_size_thread::run() {
while (!_queue.empty()) {
if (_queue.begin()->timeout < now) {
_queue.pop_front();
} else {
break;
}
}

if (!_queue.empty()) {
auto to_execute = _queue.begin();
std::list<fs_stat> stats =
os_fs_stats(*_queue.begin()->request_filter, _logger);
os_fs_stats(*to_execute->request_filter, _logger);
// main code of this program is not thread safe, so we use io_context
// launched from main thread to call callback
_io_context->post(
[result = std::move(stats),
completion_handler = std::move(_queue.begin()->handler)]() {
completion_handler = std::move(to_execute->handler)]() {
completion_handler(result);
});
_queue.pop_front();
_queue.erase(to_execute);
}
}
}
Expand Down Expand Up @@ -342,7 +345,11 @@ check_drive_size::check_drive_size(
if (args.IsObject()) {
common::rapidjson_helper helper(args);

_prct_threshold = helper.get_string("units", "%") == "%"sv;
if (args.HasMember("unit")) {
_prct_threshold = helper.get_string("unit", "%") == "%"sv;
} else {
_prct_threshold = helper.get_string("units", "%") == "%"sv;
}
_free_threshold = helper.get_bool("free", false);

_warning = helper.get_uint64_t("warning", 0);
Expand Down Expand Up @@ -416,10 +423,10 @@ e_status check_drive_size::_prct_used_test(
*/
e_status check_drive_size::_free_test(
const check_drive_size_detail::fs_stat& fs) const {
if (_critical && fs.is_free_more_than_threshold(_critical)) {
if (_critical && fs.is_free_less_than_threshold(_critical)) {
return e_status::critical;
}
if (_warning && fs.is_free_more_than_threshold(_warning)) {
if (_warning && fs.is_free_less_than_threshold(_warning)) {
return e_status::warning;
}
return e_status::ok;
Expand All @@ -433,10 +440,10 @@ e_status check_drive_size::_free_test(
*/
e_status check_drive_size::_prct_free_test(
const check_drive_size_detail::fs_stat& fs) const {
if (_critical && fs.is_free_more_than_prct_threshold(_critical)) {
if (_critical && fs.is_free_less_than_prct_threshold(_critical)) {
return e_status::critical;
}
if (_warning && fs.is_free_more_than_prct_threshold(_warning)) {
if (_warning && fs.is_free_less_than_prct_threshold(_warning)) {
return e_status::warning;
}
return e_status::ok;
Expand All @@ -454,8 +461,8 @@ void check_drive_size::start_check(const duration& timeout) {
}

if (!_worker_thread) {
_worker =
std::make_shared<check_drive_size_detail::drive_size_thread>(_logger);
_worker = std::make_shared<check_drive_size_detail::drive_size_thread>(
_io_context, _logger);
_worker_thread = new std::thread([worker = _worker] { worker->run(); });
}

Expand Down Expand Up @@ -496,18 +503,18 @@ void check_drive_size::_completion_handler(
output += fs_status == e_status::critical ? "CRITICAL: " : "WARNING: ";
if (_prct_threshold) {
output += fmt::format("{} Total: {}G Used: {:.2f}% Free: {:.2f}%",
fs.fs, fs.total / 1024 / 1024 / 1024,
fs.mount_point, fs.total / 1024 / 1024 / 1024,
fs.get_used_prct(), fs.get_free_prct());
} else {
output += fmt::format("{} Total: {}G Used: {}G Free: {}G", fs.fs,
fs.total / 1024 / 1024 / 1024,
output += fmt::format("{} Total: {}G Used: {}G Free: {}G",
fs.mount_point, fs.total / 1024 / 1024 / 1024,
fs.used / 1024 / 1024 / 1024,
(fs.total - fs.used) / 1024 / 1024 / 1024);
}
}

centreon::common::perfdata perf;
perf.name((_free_threshold ? "free_" : "used_") + fs.fs);
perf.name((_free_threshold ? "free_" : "used_") + fs.mount_point);

if (_prct_threshold) {
perf.unit("%");
Expand Down
1 change: 1 addition & 0 deletions agent/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
set( SRC_COMMON
check_test.cc
check_exec_test.cc
drive_size_test.cc
scheduler_test.cc
test_main.cc
)
Expand Down
26 changes: 14 additions & 12 deletions agent/test/check_linux_cpu_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ procs_blocked 0
softirq 166407220 66442046 14763247 1577070 4447556 33 0 18081353 30219191 75659 30801065
)";

using namespace std::string_literals;

TEST(proc_stat_file_test, no_threshold) {
constexpr const char* test_file_path = "/tmp/proc_stat_test";
{
Expand All @@ -149,8 +151,8 @@ TEST(proc_stat_file_test, no_threshold) {
rapidjson::Document check_args;

check_cpu checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -222,8 +224,8 @@ TEST(proc_stat_file_test, no_threshold_detailed) {
rapidjson::Document check_args = R"({"cpu-detailed":true})"_json;

check_cpu checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -354,8 +356,8 @@ TEST(proc_stat_file_test, threshold_nodetailed) {
R"({"warning-core" : "24.1", "critical-core" : "24.4", "warning-average" : "10", "critical-average" : "20"})"_json;

check_cpu checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -435,8 +437,8 @@ TEST(proc_stat_file_test, threshold_nodetailed2) {
R"({"warning-core-iowait" : "0.36", "critical-core-iowait" : "0.39", "warning-average-iowait" : "0.3", "critical-average-iowait" : "0.4"})"_json;

check_cpu checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -494,8 +496,8 @@ TEST(proc_stat_file_test, threshold_detailed) {
R"({"cpu-detailed":true, "warning-core" : "24.1", "critical-core" : "24.4", "warning-average" : "10", "critical-average" : "20"})"_json;

check_cpu checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -568,8 +570,8 @@ TEST(proc_stat_file_test, threshold_detailed2) {
R"({"cpu-detailed":"true", "warning-core-iowait" : "0.36", "critical-core-iowait" : "0.39", "warning-average-iowait" : "0.3", "critical-average-iowait" : "0.4"})"_json;

check_cpu checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down
29 changes: 15 additions & 14 deletions agent/test/check_uptime_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,16 @@
extern std::shared_ptr<asio::io_context> g_io_context;

using namespace com::centreon::agent;
using namespace std::string_literals;

TEST(native_check_uptime, ok) {
using namespace com::centreon::common::literals;
rapidjson::Document check_args =
R"({ "warning-uptime" : "345600", "critical-uptime" : "172800"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -62,8 +63,8 @@ TEST(native_check_uptime, ok_m) {
R"({ "warning-uptime" : "5760", "critical-uptime" : "2880", "unit": "m"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -92,8 +93,8 @@ TEST(native_check_uptime, ok_h) {
R"({ "warning-uptime" : "96", "critical-uptime" : "48", "unit": "h"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -122,8 +123,8 @@ TEST(native_check_uptime, ok_d) {
R"({ "warning-uptime" : "4", "critical-uptime" : "2", "unit": "d"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -152,8 +153,8 @@ TEST(native_check_uptime, ok_w) {
R"({ "warning-uptime" : "2", "critical-uptime" : "1", "unit": "w"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -182,8 +183,8 @@ TEST(native_check_uptime, warning) {
R"({ "warning-uptime" : "4", "critical-uptime" : "2", "unit": "d"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down Expand Up @@ -212,8 +213,8 @@ TEST(native_check_uptime, critical) {
R"({ "warning-uptime" : "4", "critical-uptime" : "2", "unit": "d"})"_json;

check_uptime checker(
g_io_context, spdlog::default_logger(), {}, {}, "serv", "cmd_name",
"cmd_line", check_args, nullptr,
g_io_context, spdlog::default_logger(), {}, {}, "serv"s, "cmd_name"s,
"cmd_line"s, check_args, nullptr,
[]([[maybe_unused]] const std::shared_ptr<check>& caller,
[[maybe_unused]] int status,
[[maybe_unused]] const std::list<com::centreon::common::perfdata>&
Expand Down
Loading

0 comments on commit e277e51

Please sign in to comment.