Skip to content

Commit e2fda01

Browse files
committed
[TEST] Make the re-entrant flush cases able to fail
Both asserted EXPECT_TRUE(flushed()), and ForceFlush() reports success when it gives up on its own condition variable, so the return value cannot tell a flush that had nothing to wait for from one that waited the whole response timeout. Inverting either ordering left both cases green at 2000 ms, the timeout they exist to rule out. Time the re-entrant flush and bound it instead. Also correct the comment on AFlushFromTheShutdownErrorDoesNotWaitForItsOwnExport. It said the export is registered before the shutdown check; the check returns first, so nothing is registered for a refused export, which is what makes the re-entrant flush return immediately on that path. Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
1 parent aa5d5f7 commit e2fda01

1 file changed

Lines changed: 22 additions & 8 deletions

File tree

‎exporters/elasticsearch/test/es_log_record_exporter_test.cc‎

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <gtest/gtest.h>
2121
#include <array>
2222
#include <atomic>
23+
#include <chrono>
2324
#include <cstddef>
2425
#include <cstdint>
2526
#include <functional>
@@ -342,6 +343,9 @@ namespace
342343
// A response timeout short enough that a wait bounded by it instead of by the caller's deadline
343344
// is visible in the elapsed time.
344345
constexpr int kShortResponseTimeoutSeconds = 2;
346+
// A flush that waits for its own export blocks until that timeout, so half of it separates
347+
// the two outcomes with a wide margin either way.
348+
constexpr std::int64_t kFlushDidNotWaitUs = kShortResponseTimeoutSeconds * 500000;
345349

346350
struct FlushFixture
347351
{
@@ -674,18 +678,26 @@ class FlushingLogHandler : public internal_log::LogHandler
674678
{
675679
return;
676680
}
677-
flushed_.store(exporter_->ForceFlush(std::chrono::milliseconds{20}), std::memory_order_relaxed);
681+
// ForceFlush() reports success when it gives up on its own condition variable, so the return
682+
// value cannot tell a flush that had nothing to wait for from one that waited the whole
683+
// response timeout. The duration can.
684+
const auto started = std::chrono::steady_clock::now();
685+
exporter_->ForceFlush(std::chrono::milliseconds{20});
686+
flush_us_.store(std::chrono::duration_cast<std::chrono::microseconds>(
687+
std::chrono::steady_clock::now() - started)
688+
.count(),
689+
std::memory_order_relaxed);
678690
}
679691

680692
bool reentered() const noexcept { return reentered_.load(std::memory_order_relaxed); }
681-
bool flushed() const noexcept { return flushed_.load(std::memory_order_relaxed); }
693+
std::int64_t flush_us() const noexcept { return flush_us_.load(std::memory_order_relaxed); }
682694
int lines() const noexcept { return lines_.load(std::memory_order_relaxed); }
683695

684696
private:
685697
logs_exporter::ElasticsearchLogRecordExporter *exporter_{nullptr};
686698
const char *needle_{"Logs were not written"};
687699
std::atomic<bool> reentered_{false};
688-
std::atomic<bool> flushed_{false};
700+
std::atomic<std::int64_t> flush_us_{0};
689701
std::atomic<int> lines_{0};
690702
};
691703
} // namespace
@@ -707,13 +719,14 @@ TEST_F(ElasticsearchAsyncCompletionTests, AFlushFromInsideTheLogHandlerDoesNotWa
707719
ExportOnce(*fixture.exporter);
708720

709721
ASSERT_TRUE(raw->reentered()) << "the failure never reached the log handler";
710-
EXPECT_TRUE(raw->flushed()) << "the flush waited for the session that was reporting itself";
722+
EXPECT_LT(raw->flush_us(), kFlushDidNotWaitUs)
723+
<< "the flush waited " << raw->flush_us() << "us for the session that was reporting itself";
711724
raw->Watch(nullptr);
712725
}
713726

714-
// The same rule on the path that refuses the batch. The export is registered before the shutdown
715-
// check, so reporting the refusal before retiring it makes a flushing handler wait for the
716-
// Export() that is calling it, and the refusal is described twice.
727+
// The same property on the path that refuses the batch: a handler that flushes from inside the
728+
// refusal must not wait for the Export() calling it. The shutdown check returns before
729+
// session_counter_ is incremented, so nothing is ever registered for a refused export.
717730
TEST_F(ElasticsearchAsyncCompletionTests, AFlushFromTheShutdownErrorDoesNotWaitForItsOwnExport)
718731
{
719732
auto fixture = MakeExporter([](const std::shared_ptr<http_client::EventHandler> &) {});
@@ -727,7 +740,8 @@ TEST_F(ElasticsearchAsyncCompletionTests, AFlushFromTheShutdownErrorDoesNotWaitF
727740
ExportOnce(*fixture.exporter);
728741

729742
ASSERT_TRUE(raw->reentered()) << "the shutdown refusal never reached the log handler";
730-
EXPECT_TRUE(raw->flushed()) << "the flush waited for the export that was refusing itself";
743+
EXPECT_LT(raw->flush_us(), kFlushDidNotWaitUs)
744+
<< "the flush waited " << raw->flush_us() << "us for the export that was refusing itself";
731745
EXPECT_EQ(1, raw->lines()) << "one refusal was described " << raw->lines() << " times";
732746
raw->Watch(nullptr);
733747
}

0 commit comments

Comments
 (0)