Repository: bitcoin/bitcoin
File: src/test/logging_tests.cpp (C++)

Code before:
    const char* log_path{utf8_path.c_str()};

    // Use GetFileSize because fs::file_size may require a flush to be accurate.
    std::streamsize log_file_size{static_cast<std::streamsize>(GetFileSize(log_path))};

    for (int64_t i{0}; i < num_lines; ++i) {
        LogFromLocation(Location::FIRST, log_message);
    }
    BOOST_CHECK(log_file_size < GetFileSize(log_path));

    log_file_size = GetFileSize(log_path);
    LogFromLocationAndExpect(Location::FIRST, log_message, "Excessive logging detected");
    BOOST_CHECK(log_file_size < GetFileSize(log_path));

    log_file_size = GetFileSize(log_path);
    LogFromLocation(Location::FIRST, log_message);
    BOOST_CHECK_EQUAL(log_file_size, GetFileSize(log_path));

    log_file_size = GetFileSize(log_path);
    LogFromLocation(Location::SECOND, log_message);
    BOOST_CHECK(log_file_size < GetFileSize(log_path));

    log_file_size = GetFileSize(log_path);
    {
        ASSERT_DEBUG_LOG("Restarting logging");
        MockForwardAndSync(scheduler, 1min);
    }
    BOOST_CHECK(log_file_size < GetFileSize(log_path));

    // Check that Location::THIRD and Location::FOURTH are exempt from rate limiting.
    for (Location location : {Location::THIRD, Location::FOURTH}) {
        log_file_size = GetFileSize(log_path);
        for (int64_t i{0}; i < num_lines; ++i) {
            LogFromLocation(location, log_message);
        }
        BOOST_CHECK(log_file_size < GetFileSize(log_path));

        // Another log statement would normally trigger the rate limit and prevent any further logs.
        log_file_size = GetFileSize(log_path);
        LogFromLocation(location, log_message);
        BOOST_CHECK(log_file_size < GetFileSize(log_path));

        // Check that the rate limit is bypassed and the file size increases.
        log_file_size = GetFileSize(log_path);
        LogFromLocation(location, log_message);
        BOOST_CHECK(log_file_size < GetFileSize(log_path));
    }

    LogInstance().m_log_timestamps = prev_log_timestamps;
    LogInstance().m_log_sourcelocations = prev_log_sourcelocations;
    LogInstance().m_log_threadnames = prev_log_threadnames;

Review comment (suggestion):
nit: use variable
```suggestion
        MockForwardAndSync(scheduler, time_window);
```

Code after:
            BOOST_CHECK(log_lines[0].starts_with("[*] [warning] Excessive logging detected"));
            log_lines.erase(log_lines.begin());
        }
        BOOST_REQUIRE_EQUAL(log_lines.size(), 1);
        auto& payload{log_lines.back()};
        BOOST_CHECK_EQUAL(suppressions_active, payload.starts_with("[*]"));
        BOOST_CHECK(payload.ends_with(message));
    }
}

} // namespace

BOOST_FIXTURE_TEST_CASE(logging_filesize_rate_limit, LogSetup)
{
    using Status = BCLog::LogRateLimiter::Status;
    LogInstance().m_log_timestamps = false;
    LogInstance().m_log_sourcelocations = false;
    LogInstance().m_log_threadnames = false;
    LogInstance().EnableCategory(BCLog::LogFlags::HTTP);

    constexpr int64_t line_length{1024};
    constexpr int64_t num_lines{1024};
    constexpr int64_t bytes_quota{line_length * num_lines};
    constexpr auto time_window{20s};

    ScopedScheduler scheduler{};
    auto limiter{scheduler.GetLimiter(bytes_quota, time_window)};
    LogInstance().SetRateLimiting(limiter);

    const std::string log_message(line_length - 1, 'a'); // subtract one for newline

    for (int i = 0; i < num_lines; ++i) {
        TestLogFromLocation(Location::INFO_1, log_message, Status::UNSUPPRESSED, /*suppressions_active=*/false);
    }
    TestLogFromLocation(Location::INFO_1, "a", Status::NEWLY_SUPPRESSED, /*suppressions_active=*/true);
    TestLogFromLocation(Location::INFO_1, "b", Status::STILL_SUPPRESSED, /*suppressions_active=*/true);
    TestLogFromLocation(Location::INFO_2, "c", Status::UNSUPPRESSED, /*suppressions_active=*/true);
    {
        scheduler.MockForwardAndSync(time_window);
        BOOST_CHECK(ReadDebugLogLines().back().starts_with("[warning] Restarting logging"));
    }
    // Check that logging from previously suppressed location is unsuppressed again.
    TestLogFromLocation(Location::INFO_1, log_message, Status::UNSUPPRESSED, /*suppressions_active=*/false);
    // Check that conditional logging, and unconditional logging with should_ratelimit=false is
    // not being ratelimited.
    for (Location location : {Location::DEBUG_LOG, Location::INFO_NOLIMIT}) {
        for (int i = 0; i < num_lines + 2; ++i) {
            TestLogFromLocation(location, log_message, Status::UNSUPPRESSED, /*suppressions_active=*/false);
        }
    }
}