Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
test_cross_system_integration.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
18#include <gtest/gtest.h>
20#include <kcenon/common/interfaces/logger_interface.h>
21#include <kcenon/common/interfaces/monitoring_interface.h>
22#include <memory>
23#include <mutex>
24#include <thread>
25#include <chrono>
26
27// Use explicit namespace aliases to avoid conflicts
28namespace common_if = kcenon::common::interfaces;
29namespace mon = kcenon::monitoring;
30
31using kcenon::common::VoidResult;
32using kcenon::common::Result;
33
39class simple_mock_logger : public common_if::ILogger, public common_if::IMonitorable {
40private:
41 std::shared_ptr<common_if::IMonitor> monitor_;
42 int log_count_{0};
43
44public:
45 VoidResult log([[maybe_unused]] common_if::log_level level,
46 [[maybe_unused]] const std::string& message) override {
47 log_count_++;
48 if (monitor_) {
49 monitor_->record_metric("logs_written", static_cast<double>(log_count_));
50 }
51 return kcenon::common::ok();
52 }
53
54 VoidResult log(const common_if::log_entry& entry) override {
55 return log(entry.level, entry.message);
56 }
57
58 bool is_enabled([[maybe_unused]] common_if::log_level level) const override { return true; }
59 VoidResult set_level([[maybe_unused]] common_if::log_level level) override { return kcenon::common::ok(); }
60 common_if::log_level get_level() const override { return common_if::log_level::info; }
61 VoidResult flush() override { return kcenon::common::ok(); }
62
63 // IMonitorable implementation (using common_system types)
64 Result<common_if::metrics_snapshot> get_monitoring_data() override {
65 common_if::metrics_snapshot snapshot;
66 snapshot.source_id = "simple_mock_logger";
67 snapshot.add_metric("total_logs", static_cast<double>(log_count_));
68 return snapshot;
69 }
70
71 Result<common_if::health_check_result> health_check() override {
72 common_if::health_check_result result;
73 result.status = common_if::health_status::healthy;
74 result.message = "Mock logger operational";
75 return result;
76 }
77
78 std::string get_component_name() const override {
79 return "simple_mock_logger";
80 }
81
82 // For bidirectional DI
83 void set_monitor(std::shared_ptr<common_if::IMonitor> monitor) {
84 monitor_ = monitor;
85 }
86
87 int get_log_count() const { return log_count_; }
88};
89
95class mock_monitor : public common_if::IMonitor {
96private:
97 std::vector<common_if::metric_value> metrics_;
98 mutable std::mutex mutex_;
99
100public:
101 VoidResult record_metric(const std::string& name, double value) override {
102 std::lock_guard<std::mutex> lock(mutex_);
103 metrics_.emplace_back(name, value);
104 return kcenon::common::ok();
105 }
106
107 VoidResult record_metric(
108 const std::string& name,
109 double value,
110 const std::unordered_map<std::string, std::string>& tags) override {
111 std::lock_guard<std::mutex> lock(mutex_);
112 common_if::metric_value mv(name, value);
113 mv.tags = tags;
114 metrics_.push_back(mv);
115 return kcenon::common::ok();
116 }
117
118 Result<common_if::metrics_snapshot> get_metrics() override {
119 std::lock_guard<std::mutex> lock(mutex_);
120 common_if::metrics_snapshot snapshot;
121 snapshot.metrics = metrics_;
122 snapshot.source_id = "mock_monitor";
123 return snapshot;
124 }
125
126 Result<common_if::health_check_result> check_health() override {
127 common_if::health_check_result result;
128 result.status = common_if::health_status::healthy;
129 result.message = "Mock monitor operational";
130 return result;
131 }
132
133 VoidResult reset() override {
134 std::lock_guard<std::mutex> lock(mutex_);
135 metrics_.clear();
136 return kcenon::common::ok();
137 }
138
139 size_t get_metric_count() const {
140 std::lock_guard<std::mutex> lock(mutex_);
141 return metrics_.size();
142 }
143};
144
148TEST(CrossSystemIntegrationTest, BothSystemsStandalone) {
149 // Create logger without monitor
150 auto logger = std::make_shared<simple_mock_logger>();
151
152 EXPECT_NO_THROW({
153 logger->log(common_if::log_level::info, "Test message");
154 });
155 EXPECT_EQ(1, logger->get_log_count());
156
157 // Create monitor without logger
158 auto monitor = std::make_shared<mock_monitor>();
159
160 EXPECT_NO_THROW({
161 auto result = monitor->record_metric("test_metric", 1.0);
162 EXPECT_TRUE(result.is_ok());
163 });
164
165 // Both should work independently
166 auto monitor_metrics = monitor->get_metrics();
167 ASSERT_TRUE(monitor_metrics.is_ok());
168 EXPECT_EQ(1, monitor_metrics.value().metrics.size());
169}
170
174TEST(CrossSystemIntegrationTest, LoggerWithMonitorInjection) {
175 auto monitor = std::make_shared<mock_monitor>();
176 auto logger = std::make_shared<simple_mock_logger>();
177
178 // Inject monitor into logger
179 logger->set_monitor(monitor);
180
181 // Log messages - each log should record a metric
182 logger->log(common_if::log_level::info, "Test 1");
183 logger->log(common_if::log_level::info, "Test 2");
184
185 // Monitor should have received metrics from logger
186 auto metrics_result = monitor->get_metrics();
187 ASSERT_TRUE(metrics_result.is_ok());
188
189 auto& snapshot = metrics_result.value();
190 EXPECT_EQ(2, snapshot.metrics.size());
191}
192
196TEST(CrossSystemIntegrationTest, MonitorInterfaceCompatibility) {
197 auto monitor = std::make_shared<mock_monitor>();
198
199 // Test IMonitor interface methods
200 EXPECT_NO_THROW({
201 auto result = monitor->record_metric("test_metric", 42.0);
202 EXPECT_TRUE(result.is_ok());
203 });
204
205 // Monitor health check should work
206 auto health = monitor->check_health();
207 ASSERT_TRUE(health.is_ok());
208 EXPECT_EQ(common_if::health_status::healthy, health.value().status);
209}
210
217TEST(CrossSystemIntegrationTest, BidirectionalDependencyInjection) {
218 // Create both systems
219 auto logger = std::make_shared<simple_mock_logger>();
220 auto monitor = std::make_shared<mock_monitor>();
221
222 // Bidirectional injection
223 logger->set_monitor(monitor);
224
225 // Use both systems
226 for (int i = 0; i < 10; ++i) {
227 logger->log(common_if::log_level::info, "Request " + std::to_string(i));
228 }
229
230 // Verify logger health
231 auto logger_health = logger->health_check();
232 ASSERT_TRUE(logger_health.is_ok());
233 EXPECT_TRUE(logger_health.value().is_healthy());
234
235 // Verify monitor health
236 auto monitor_health = monitor->check_health();
237 ASSERT_TRUE(monitor_health.is_ok());
238 EXPECT_TRUE(monitor_health.value().is_healthy());
239
240 // Verify metrics were recorded
241 auto monitor_metrics = monitor->get_metrics();
242 ASSERT_TRUE(monitor_metrics.is_ok());
243 EXPECT_EQ(10, monitor_metrics.value().metrics.size());
244
245 // Logger should have logged
246 EXPECT_EQ(10, logger->get_log_count());
247}
248
252TEST(CrossSystemIntegrationTest, RepeatedInjection) {
253 auto logger = std::make_shared<simple_mock_logger>();
254 auto monitor1 = std::make_shared<mock_monitor>();
255 auto monitor2 = std::make_shared<mock_monitor>();
256
257 // First injection
258 logger->set_monitor(monitor1);
259 logger->log(common_if::log_level::info, "With monitor1");
260
261 // monitor1 should have received the metric
262 EXPECT_EQ(1, monitor1->get_metric_count());
263
264 // Replace with second monitor
265 logger->set_monitor(monitor2);
266 logger->log(common_if::log_level::info, "With monitor2");
267
268 // monitor2 should now receive metrics, monitor1 stays at 1
269 EXPECT_EQ(1, monitor1->get_metric_count());
270 EXPECT_EQ(1, monitor2->get_metric_count());
271 EXPECT_EQ(2, logger->get_log_count());
272}
273
277TEST(CrossSystemIntegrationTest, NullInjection) {
278 auto logger = std::make_shared<simple_mock_logger>();
279 auto monitor = std::make_shared<mock_monitor>();
280
281 // Inject then remove
282 logger->set_monitor(monitor);
283 logger->set_monitor(nullptr);
284
285 // Should not crash
286 EXPECT_NO_THROW({
287 logger->log(common_if::log_level::info, "After null injection");
288 });
289
290 EXPECT_EQ(1, logger->get_log_count());
291 // Monitor should not have received the last log (null injection)
292 EXPECT_EQ(0, monitor->get_metric_count());
293}
294
298TEST(CrossSystemIntegrationTest, IntegrationPerformanceOverhead) {
299 auto logger = std::make_shared<simple_mock_logger>();
300 auto monitor = std::make_shared<mock_monitor>();
301
302 logger->set_monitor(monitor);
303
304 // Measure time for integrated operations
305 auto start = std::chrono::high_resolution_clock::now();
306
307 for (int i = 0; i < 1000; ++i) {
308 logger->log(common_if::log_level::info, "Performance test");
309 }
310
311 auto end = std::chrono::high_resolution_clock::now();
312 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
313
314 // Integration should be fast (< 100ms for 1000 operations)
315 EXPECT_LT(duration.count(), 100);
316 EXPECT_EQ(1000, monitor->get_metric_count());
317}
318
322TEST(CrossSystemIntegrationTest, MonitoringSystemStandalone) {
323 auto monitor = std::make_shared<mon::performance_monitor>();
324
325 // Test monitoring_system's native interface
326 EXPECT_NO_THROW({
327 auto timer = monitor->time_operation("test_op");
328 // Simulate work
329 std::this_thread::sleep_for(std::chrono::milliseconds(1));
330 });
331
332 // Collect metrics using native interface
333 auto result = monitor->collect();
334 ASSERT_TRUE(result.is_ok());
335}
336
337int main(int argc, char** argv) {
338 ::testing::InitGoogleTest(&argc, argv);
339 return RUN_ALL_TESTS();
340}
Mock IMonitor for testing cross-system integration.
VoidResult record_metric(const std::string &name, double value) override
std::vector< common_if::metric_value > metrics_
Result< common_if::metrics_snapshot > get_metrics() override
Result< common_if::health_check_result > check_health() override
VoidResult reset() override
VoidResult record_metric(const std::string &name, double value, const std::unordered_map< std::string, std::string > &tags) override
Simple mock logger for testing.
bool is_enabled(common_if::log_level level) const override
VoidResult log(const common_if::log_entry &entry) override
Result< common_if::metrics_snapshot > get_monitoring_data() override
common_if::log_level get_level() const override
std::shared_ptr< common_if::IMonitor > monitor_
Result< common_if::health_check_result > health_check() override
void set_monitor(std::shared_ptr< common_if::IMonitor > monitor)
VoidResult log(common_if::log_level level, const std::string &message) override
VoidResult set_level(common_if::log_level level) override
std::string get_component_name() const override
Performance monitoring and profiling implementation.
TEST(CrossSystemIntegrationTest, BothSystemsStandalone)
Test Case 1: Both systems standalone.