diff --git a/README.md b/README.md index 81fd75e..38b05ce 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ make coverage # Code coverage report (requires lcov) include(FetchContent) FetchContent_Declare(ncei-cpp GIT_REPOSITORY https://github.com/Reddimus/ncei-cpp.git - GIT_TAG v0.3.0 + GIT_TAG v0.3.1 ) FetchContent_MakeAvailable(ncei-cpp) target_link_libraries(myapp PRIVATE ncei) diff --git a/src/core/rate_limit.cpp b/src/core/rate_limit.cpp index db0c6cf..48d132a 100644 --- a/src/core/rate_limit.cpp +++ b/src/core/rate_limit.cpp @@ -1,5 +1,7 @@ #include "ncei/rate_limit.hpp" +#include + namespace ncei { RateLimiter::RateLimiter(Config config) @@ -81,7 +83,11 @@ std::uint16_t RateLimiter::available_tokens() const noexcept { std::int32_t RateLimiter::daily_requests_remaining() const noexcept { std::lock_guard lock(mutex_); if (config_.daily_limit <= 0) { - return 0; + // daily_limit <= 0 means "no daily cap" (see rate_limit.hpp). Signal + // unlimited headroom — NOT 0, which callers (CDOClient::do_get) treat + // as quota-exhausted and would reject every request when the cap is + // intentionally disabled. + return std::numeric_limits::max(); } return config_.daily_limit - daily_requests_used_; } diff --git a/tests/test_rate_limit.cpp b/tests/test_rate_limit.cpp index d48d534..450faba 100644 --- a/tests/test_rate_limit.cpp +++ b/tests/test_rate_limit.cpp @@ -1,6 +1,8 @@ #include "ncei/rate_limit.hpp" +#include #include +#include namespace ncei { namespace { @@ -127,6 +129,12 @@ TEST(RateLimiterTest, NoDailyLimitWhenZero) { EXPECT_TRUE(limiter.try_acquire()); EXPECT_TRUE(limiter.try_acquire()); EXPECT_TRUE(limiter.try_acquire()); + + // Regression: a disabled daily limit must report "unlimited" headroom, NOT + // 0. CDOClient::do_get() rejects with quota_exceeded when remaining <= 0, so + // returning 0 here would block every request whenever the cap is disabled. + EXPECT_GT(limiter.daily_requests_remaining(), 0); + EXPECT_EQ(limiter.daily_requests_remaining(), std::numeric_limits::max()); } TEST(RateLimiterTest, DailyCounterResetsOnReset) {