Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
test_gpu_collector.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
5#include <gtest/gtest.h>
7
8namespace kcenon {
9namespace monitoring {
10namespace {
11
12// Test fixture for GPU collector tests
13class GpuCollectorTest : public ::testing::Test {
14 protected:
15 void SetUp() override {
16 collector_ = std::make_unique<gpu_collector>();
17 std::unordered_map<std::string, std::string> config;
18 collector_->initialize(config);
19 }
20
21 std::unique_ptr<gpu_collector> collector_;
22};
23
24// Test basic initialization
25TEST_F(GpuCollectorTest, InitializesSuccessfully) {
26 EXPECT_EQ(collector_->name(), "gpu");
27}
28
29// Test metric types returned
30TEST_F(GpuCollectorTest, ReturnsCorrectMetricTypes) {
31 auto metric_types = collector_->get_metric_types();
32
33 // Should include all expected GPU metrics
34 EXPECT_FALSE(metric_types.empty());
35
36 // Check for expected metric types
37 auto contains = [&metric_types](const std::string& type) {
38 return std::find(metric_types.begin(), metric_types.end(), type) != metric_types.end();
39 };
40
41 EXPECT_TRUE(contains("gpu_utilization_percent"));
42 EXPECT_TRUE(contains("gpu_memory_used_bytes"));
43 EXPECT_TRUE(contains("gpu_memory_total_bytes"));
44 EXPECT_TRUE(contains("gpu_memory_usage_percent"));
45 EXPECT_TRUE(contains("gpu_temperature_celsius"));
46 EXPECT_TRUE(contains("gpu_power_watts"));
47 EXPECT_TRUE(contains("gpu_clock_mhz"));
48 EXPECT_TRUE(contains("gpu_fan_speed_percent"));
49}
50
51// Test configuration options
52TEST_F(GpuCollectorTest, ConfigurationOptions) {
53 auto custom_collector = std::make_unique<gpu_collector>();
54
55 std::unordered_map<std::string, std::string> config = {
56 {"enabled", "true"},
57 {"collect_utilization", "true"},
58 {"collect_memory", "true"},
59 {"collect_temperature", "true"},
60 {"collect_power", "true"},
61 {"collect_clock", "true"},
62 {"collect_fan", "true"}};
63
64 EXPECT_TRUE(custom_collector->initialize(config));
65}
66
67// Test disable collector
68TEST_F(GpuCollectorTest, CanBeDisabled) {
69 auto custom_collector = std::make_unique<gpu_collector>();
70
71 std::unordered_map<std::string, std::string> config = {{"enabled", "false"}};
72
73 custom_collector->initialize(config);
74
75 // When disabled, collect should return empty
76 auto metrics = custom_collector->collect();
77 EXPECT_TRUE(metrics.empty());
78}
79
80// Test statistics
81TEST_F(GpuCollectorTest, TracksStatistics) {
82 auto stats = collector_->get_statistics();
83
84 // Should have expected statistics keys
85 EXPECT_TRUE(stats.find("collection_count") != stats.end());
86 EXPECT_TRUE(stats.find("collection_errors") != stats.end());
87 EXPECT_TRUE(stats.find("gpus_found") != stats.end());
88
89 // Initial values should be 0
90 EXPECT_EQ(stats["collection_count"], 0.0);
91 EXPECT_EQ(stats["collection_errors"], 0.0);
92}
93
94// Test collect returns metrics (graceful degradation when GPUs unavailable)
95TEST_F(GpuCollectorTest, CollectReturnsMetrics) {
96 auto metrics = collector_->collect();
97
98 // This may return empty metrics if GPUs are not available
99 // This is expected behavior - graceful degradation
100 auto stats = collector_->get_statistics();
101 EXPECT_GE(stats["collection_count"], 1.0);
102}
103
104// Test get_last_readings
105TEST_F(GpuCollectorTest, GetLastReadings) {
106 collector_->collect();
107 auto last_readings = collector_->get_last_readings();
108
109 // Should return vector (may be empty if GPU not available)
110 // No assertion - just verify it doesn't crash
111 (void)last_readings;
112}
113
114// Test is_gpu_available
115TEST_F(GpuCollectorTest, GpuAvailabilityCheck) {
116 // Should not crash - returns true/false based on GPU availability
117 bool available = collector_->is_gpu_available();
118 (void)available; // Use the variable to avoid warning
119}
120
121// Test gpu_reading structure
122TEST(GpuReadingTest, DefaultInitialization) {
123 gpu_reading reading;
124
125 EXPECT_TRUE(reading.device.id.empty());
126 EXPECT_TRUE(reading.device.name.empty());
127 EXPECT_EQ(reading.device.vendor, gpu_vendor::unknown);
128 EXPECT_EQ(reading.device.type, gpu_type::unknown);
129 EXPECT_EQ(reading.utilization_percent, 0.0);
130 EXPECT_EQ(reading.memory_used_bytes, 0u);
131 EXPECT_EQ(reading.memory_total_bytes, 0u);
132 EXPECT_EQ(reading.temperature_celsius, 0.0);
133 EXPECT_EQ(reading.power_watts, 0.0);
134 EXPECT_EQ(reading.clock_mhz, 0.0);
135 EXPECT_EQ(reading.fan_speed_percent, 0.0);
136 EXPECT_FALSE(reading.utilization_available);
137 EXPECT_FALSE(reading.memory_available);
138 EXPECT_FALSE(reading.temperature_available);
139 EXPECT_FALSE(reading.power_available);
140 EXPECT_FALSE(reading.clock_available);
141 EXPECT_FALSE(reading.fan_available);
142}
143
144// Test gpu_device_info structure
145TEST(GpuDeviceInfoTest, DefaultInitialization) {
146 gpu_device_info info;
147
148 EXPECT_TRUE(info.id.empty());
149 EXPECT_TRUE(info.name.empty());
150 EXPECT_TRUE(info.device_path.empty());
151 EXPECT_TRUE(info.driver_version.empty());
152 EXPECT_EQ(info.vendor, gpu_vendor::unknown);
153 EXPECT_EQ(info.type, gpu_type::unknown);
154 EXPECT_EQ(info.device_index, 0u);
155}
156
157// Test gpu_vendor_to_string conversion
158TEST(GpuVendorTest, VendorToStringConversion) {
159 EXPECT_EQ(gpu_vendor_to_string(gpu_vendor::nvidia), "nvidia");
160 EXPECT_EQ(gpu_vendor_to_string(gpu_vendor::amd), "amd");
161 EXPECT_EQ(gpu_vendor_to_string(gpu_vendor::intel), "intel");
162 EXPECT_EQ(gpu_vendor_to_string(gpu_vendor::apple), "apple");
163 EXPECT_EQ(gpu_vendor_to_string(gpu_vendor::other), "other");
164 EXPECT_EQ(gpu_vendor_to_string(gpu_vendor::unknown), "unknown");
165}
166
167// Test gpu_type_to_string conversion
168TEST(GpuTypeTest, TypeToStringConversion) {
169 EXPECT_EQ(gpu_type_to_string(gpu_type::discrete), "discrete");
170 EXPECT_EQ(gpu_type_to_string(gpu_type::integrated), "integrated");
171 EXPECT_EQ(gpu_type_to_string(gpu_type::virtual_gpu), "virtual");
172 EXPECT_EQ(gpu_type_to_string(gpu_type::unknown), "unknown");
173}
174
175// Test gpu_info_collector basic functionality
176TEST(GpuInfoCollectorTest, BasicFunctionality) {
177 gpu_info_collector collector;
178
179 // Test GPU availability check (should not crash)
180 bool available = collector.is_gpu_available();
181
182 // If GPU is not available, enumerate_gpus should still work
183 if (!available) {
184 auto gpus = collector.enumerate_gpus();
185 // Empty GPUs without GPU is acceptable
186 (void)gpus;
187 } else {
188 // If GPU is available, we might get some devices
189 auto gpus = collector.enumerate_gpus();
190 // Just verify it doesn't crash - actual device count depends on system
191 (void)gpus;
192 }
193}
194
195// Test GPU enumeration (graceful degradation)
196TEST(GpuInfoCollectorTest, EnumerateGpus) {
197 gpu_info_collector collector;
198
199 auto gpus = collector.enumerate_gpus();
200
201 // Should return a vector (may be empty if GPU not available)
202 // No assertion on size - just verify it doesn't crash
203 (void)gpus;
204}
205
206// Test multiple collections don't cause issues
207TEST_F(GpuCollectorTest, MultipleCollectionsAreStable) {
208 for (int i = 0; i < 5; ++i) {
209 auto metrics = collector_->collect();
210 // Should not crash on repeated calls
211 (void)metrics;
212 }
213
214 auto stats = collector_->get_statistics();
215 EXPECT_GE(stats["collection_count"], 5.0);
216 EXPECT_EQ(stats["collection_errors"], 0.0);
217}
218
219// Test that metrics have correct tags when collected
220TEST_F(GpuCollectorTest, MetricsHaveCorrectTags) {
221 auto metrics = collector_->collect();
222
223 for (const auto& m : metrics) {
224 // If we have any metrics, check they have the expected tags
225 if (!m.name.empty()) {
226 EXPECT_TRUE(m.tags.find("gpu_id") != m.tags.end());
227 EXPECT_TRUE(m.tags.find("gpu_name") != m.tags.end());
228 EXPECT_TRUE(m.tags.find("gpu_vendor") != m.tags.end());
229 EXPECT_TRUE(m.tags.find("gpu_type") != m.tags.end());
230 EXPECT_TRUE(m.tags.find("gpu_index") != m.tags.end());
231 }
232 }
233}
234
235// Test read_all_gpu_metrics
236TEST(GpuInfoCollectorTest, ReadAllGpuMetrics) {
237 gpu_info_collector collector;
238
239 auto readings = collector.read_all_gpu_metrics();
240
241 // Should return a vector (may be empty if GPU not available)
242 // No assertion on size - just verify it doesn't crash
243 for (const auto& reading : readings) {
244 // If we got readings, they should have valid device info
245 EXPECT_FALSE(reading.device.id.empty());
246 }
247}
248
249// Test selective metric collection
250TEST_F(GpuCollectorTest, SelectiveMetricCollection) {
251 auto custom_collector = std::make_unique<gpu_collector>();
252
253 // Only collect temperature
254 std::unordered_map<std::string, std::string> config = {
255 {"enabled", "true"},
256 {"collect_utilization", "false"},
257 {"collect_memory", "false"},
258 {"collect_temperature", "true"},
259 {"collect_power", "false"},
260 {"collect_clock", "false"},
261 {"collect_fan", "false"}};
262
263 EXPECT_TRUE(custom_collector->initialize(config));
264
265 // Collection should work
266 auto metrics = custom_collector->collect();
267 (void)metrics; // Just verify it runs
268}
269
270// Test that collector handles reinitialize gracefully
271TEST_F(GpuCollectorTest, ReinitializeHandledGracefully) {
272 // First initialization
273 std::unordered_map<std::string, std::string> config1 = {{"enabled", "true"}};
274 EXPECT_TRUE(collector_->initialize(config1));
275 collector_->collect();
276
277 // Second initialization with different config
278 std::unordered_map<std::string, std::string> config2 = {{"enabled", "false"}};
279 EXPECT_TRUE(collector_->initialize(config2));
280
281 // Should now return empty
282 auto metrics = collector_->collect();
283 EXPECT_TRUE(metrics.empty());
284}
285
286} // namespace
287} // namespace monitoring
288} // namespace kcenon
GPU metrics monitoring collector.
std::string gpu_vendor_to_string(gpu_vendor vendor)
Convert gpu_vendor to string representation.
@ virtual_gpu
Virtual GPU (cloud/VM)
@ discrete
Discrete GPU (dedicated graphics card)
@ unknown
Unknown GPU type.
@ integrated
Integrated GPU (part of CPU/SoC)
std::string gpu_type_to_string(gpu_type type)
Convert gpu_type to string representation.
@ info
Informational, no action required.
@ apple
Apple (Apple Silicon GPU)
@ intel
Intel Corporation.
@ nvidia
NVIDIA Corporation.
@ amd
Advanced Micro Devices.
TEST(AdapterFunctionalityTest, WorksWithoutLogger)
Test Scenario 1: Adapter with NULL logger.
TEST_F(AdaptiveMonitoringTest, AdaptiveConfigDefaults)
std::unique_ptr< battery_collector > collector_