5#include <gtest/gtest.h>
31 return kcenon::common::ok(42);
35 void simulate_work(std::chrono::milliseconds duration = std::chrono::milliseconds(10)) {
36 std::this_thread::sleep_for(duration);
45 EXPECT_TRUE(limiter->try_acquire(1));
46 EXPECT_TRUE(limiter->try_acquire(5));
49 EXPECT_FALSE(limiter->try_acquire(10));
56 for (
int i = 0; i < 10; ++i) {
57 EXPECT_TRUE(limiter->try_acquire(1));
59 EXPECT_FALSE(limiter->try_acquire(1));
62 std::this_thread::sleep_for(std::chrono::milliseconds(200));
65 EXPECT_TRUE(limiter->try_acquire(1));
70 throttling_strategy::reject);
73 for (
int i = 0; i < 5; ++i) {
74 auto result = limiter->execute([
this]() {
return test_operation(); });
75 EXPECT_TRUE(result.is_ok());
76 EXPECT_EQ(result.value(), 42);
80 auto result = limiter->execute([
this]() {
return test_operation(); });
81 EXPECT_TRUE(result.is_err());
82 EXPECT_EQ(
static_cast<monitoring_error_code>(result.error().code), monitoring_error_code::resource_exhausted);
90 EXPECT_TRUE(limiter->try_acquire(1));
91 EXPECT_TRUE(limiter->try_acquire(5));
94 EXPECT_FALSE(limiter->try_acquire(10));
101 for (
int i = 0; i < 5; ++i) {
102 EXPECT_TRUE(limiter->try_acquire(1));
104 EXPECT_FALSE(limiter->try_acquire(1));
107 std::this_thread::sleep_for(std::chrono::milliseconds(100));
110 EXPECT_TRUE(limiter->try_acquire(1));
116 throttling_strategy::reject);
119 auto result1 = manager->allocate(512);
120 EXPECT_TRUE(result1.is_ok());
121 EXPECT_EQ(manager->current_usage(), 512);
124 auto result2 = manager->allocate(256);
125 EXPECT_TRUE(result2.is_ok());
126 EXPECT_EQ(manager->current_usage(), 768);
129 auto result3 = manager->allocate(512);
130 EXPECT_TRUE(result3.is_err());
131 EXPECT_EQ(
static_cast<monitoring_error_code>(result3.error().code), monitoring_error_code::resource_exhausted);
138 auto result = manager->allocate(512);
139 EXPECT_TRUE(result.is_ok());
140 EXPECT_EQ(manager->current_usage(), 512);
143 manager->deallocate(256);
144 EXPECT_EQ(manager->current_usage(), 256);
147 result = manager->allocate(512);
148 EXPECT_TRUE(result.is_ok());
149 EXPECT_EQ(manager->current_usage(), 768);
153 resource_quota quota(resource_type::memory, 1000, throttling_strategy::reject);
157 auto manager = std::make_unique<memory_quota_manager>(
"test_memory", quota);
160 EXPECT_FALSE(manager->is_over_warning_threshold());
161 EXPECT_FALSE(manager->is_over_critical_threshold());
164 manager->allocate(750);
165 EXPECT_TRUE(manager->is_over_warning_threshold());
166 EXPECT_FALSE(manager->is_over_critical_threshold());
169 manager->allocate(150);
170 EXPECT_TRUE(manager->is_over_warning_threshold());
171 EXPECT_TRUE(manager->is_over_critical_threshold());
178 auto metrics = manager->get_metrics();
179 EXPECT_EQ(metrics.current_usage.load(), 0);
180 EXPECT_EQ(metrics.total_allocations.load(), 0);
183 manager->allocate(512);
184 metrics = manager->get_metrics();
185 EXPECT_EQ(metrics.current_usage.load(), 512);
186 EXPECT_EQ(metrics.total_allocations.load(), 1);
187 EXPECT_EQ(metrics.peak_usage.load(), 512);
190 manager->allocate(256);
191 metrics = manager->get_metrics();
192 EXPECT_EQ(metrics.peak_usage.load(), 768);
199 config.
strategy = throttling_strategy::reject;
202 auto throttler = std::make_unique<cpu_throttler>(
"test_cpu", config);
205 auto result = throttler->execute([
this]() {
return test_operation(); });
206 EXPECT_TRUE(result.is_ok());
207 EXPECT_EQ(result.value(), 42);
213 config.
strategy = throttling_strategy::delay;
215 auto throttler = std::make_unique<cpu_throttler>(
"test_cpu", config);
218 throttler->execute([
this]() {
return test_operation(); });
220 auto metrics = throttler->get_metrics();
221 EXPECT_EQ(metrics.total_allocations.load(), 1);
232 auto result = manager->add_rate_limiter(
"api_limiter", config);
233 EXPECT_TRUE(result.is_ok());
235 auto limiter = manager->get_rate_limiter(
"api_limiter");
236 EXPECT_NE(limiter,
nullptr);
237 EXPECT_EQ(limiter->get_name(),
"api_limiter");
243 resource_quota quota(resource_type::memory, 2048, throttling_strategy::reject);
245 auto result = manager->add_memory_quota(
"memory_quota", quota);
246 EXPECT_TRUE(result.is_ok());
248 auto memory_manager = manager->get_memory_quota(
"memory_quota");
249 EXPECT_NE(memory_manager,
nullptr);
250 EXPECT_EQ(memory_manager->get_name(),
"memory_quota");
258 config.
strategy = throttling_strategy::delay;
260 auto result = manager->add_cpu_throttler(
"cpu_throttler", config);
261 EXPECT_TRUE(result.is_ok());
263 auto throttler = manager->get_cpu_throttler(
"cpu_throttler");
264 EXPECT_NE(throttler,
nullptr);
265 EXPECT_EQ(throttler->get_name(),
"cpu_throttler");
276 auto result1 = manager->add_rate_limiter(
"duplicate_name", config);
277 EXPECT_TRUE(result1.is_ok());
280 auto result2 = manager->add_rate_limiter(
"duplicate_name", config);
281 EXPECT_TRUE(result2.is_err());
282 EXPECT_EQ(
static_cast<monitoring_error_code>(result2.error().code), monitoring_error_code::already_exists);
289 resource_quota quota(resource_type::memory, 1024, throttling_strategy::reject);
290 manager->add_memory_quota(
"memory", quota);
294 manager->add_cpu_throttler(
"cpu", cpu_config);
297 auto health = manager->is_healthy();
298 EXPECT_TRUE(health.is_ok());
299 EXPECT_TRUE(health.value());
309 manager->add_rate_limiter(
"rate", rate_config);
312 resource_quota quota(resource_type::memory, 1024, throttling_strategy::reject);
313 manager->add_memory_quota(
"memory", quota);
316 auto all_metrics = manager->get_all_metrics();
317 EXPECT_EQ(all_metrics.size(), 2);
318 EXPECT_TRUE(all_metrics.find(
"rate_rate") != all_metrics.end());
319 EXPECT_TRUE(all_metrics.find(
"memory_memory") != all_metrics.end());
345 quota.
type = resource_type::memory;
389 throttling_strategy::reject);
391 const int num_threads = 10;
392 const int operations_per_thread = 10;
393 std::atomic<int> successful_operations{0};
395 std::vector<std::thread> threads;
396 for (
int i = 0; i < num_threads; ++i) {
397 threads.emplace_back([&]() {
398 for (
int j = 0; j < operations_per_thread; ++j) {
399 if (limiter->try_acquire(1)) {
400 successful_operations++;
406 for (
auto& thread : threads) {
411 EXPECT_GT(successful_operations.load(), 0);
412 EXPECT_LE(successful_operations.load(), 100);
417 throttling_strategy::reject);
419 const int num_threads = 5;
420 const int allocations_per_thread = 10;
421 std::atomic<int> successful_allocations{0};
423 std::vector<std::thread> threads;
424 for (
int i = 0; i < num_threads; ++i) {
425 threads.emplace_back([&]() {
426 for (
int j = 0; j < allocations_per_thread; ++j) {
427 if (manager->allocate(500).is_ok()) {
428 successful_allocations++;
430 simulate_work(std::chrono::milliseconds(1));
431 manager->deallocate(500);
437 for (
auto& thread : threads) {
441 EXPECT_GT(successful_allocations.load(), 0);
442 EXPECT_EQ(manager->current_usage(), 0);
449 const int num_operations = 1000;
450 auto start = std::chrono::steady_clock::now();
452 for (
int i = 0; i < num_operations; ++i) {
453 limiter->try_acquire(1);
456 auto end = std::chrono::steady_clock::now();
457 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
461 EXPECT_LT(duration.count(), 100000);
467 const int num_operations = 1000;
468 auto start = std::chrono::steady_clock::now();
470 for (
int i = 0; i < num_operations; ++i) {
471 manager->allocate(100);
472 manager->deallocate(100);
475 auto end = std::chrono::steady_clock::now();
476 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
480 EXPECT_LT(duration.count(), 50000);
std::atomic< int > success_count
kcenon::common::Result< int > test_operation()
std::atomic< int > call_count
void simulate_work(std::chrono::milliseconds duration=std::chrono::milliseconds(10))
std::unique_ptr< memory_quota_manager > create_memory_quota_manager(const std::string &name, size_t max_bytes, throttling_strategy strategy=throttling_strategy::reject)
Create a memory quota manager.
std::unique_ptr< token_bucket_limiter > create_token_bucket_limiter(const std::string &name, double rate, size_t capacity, throttling_strategy strategy=throttling_strategy::reject)
Create a token bucket rate limiter.
std::unique_ptr< resource_manager > create_resource_manager(const std::string &name)
Create a resource manager.
monitoring_error_code
Comprehensive error codes for monitoring system operations.
std::unique_ptr< leaky_bucket_limiter > create_leaky_bucket_limiter(const std::string &name, double rate, size_t capacity)
Create a leaky bucket rate limiter.
Resource exhaustion handling strategies and limits.
Configuration for CPU throttling.
bool validate() const
Validate configuration.
double max_cpu_usage
Maximum CPU usage (0.0 to 1.0)
double warning_threshold
Warning threshold (0.0 to 1.0)
std::chrono::milliseconds check_interval
throttling_strategy strategy
Configuration for rate limiting.
size_t burst_capacity
Maximum burst capacity.
double rate_per_second
Rate of token refill per second.
bool validate() const
Validate configuration.
Configuration for resource quotas.
size_t critical_threshold
Critical level threshold.
size_t max_value
Maximum allowed resource usage.
size_t warning_threshold
Warning level threshold.
bool validate() const
Validate configuration.
TEST_F(ResourceManagementTest, TokenBucketBasicOperation)