| #include <thread> // NOLINT(build/c++11) | |
| #include <vector> | |
| #include "event.h" | |
| #include "event_queue.h" | |
| #include "gmock/gmock.h" | |
| #include "gtest/gtest.h" | |
| #include "absl/status/status.h" | |
| #include "absl/time/clock.h" | |
| #include "absl/time/time.h" | |
| #include "bmc/test_util.h" | |
| namespace safepower_agent { | |
| namespace { | |
| TEST(EventQueueThreadTest, PushAndPopSingleEvent) { | |
| EventQueue queue; | |
| queue.Push(Event{}); | |
| ASSERT_OK_AND_ASSIGN(auto events, | |
| queue.PopAllWithTimeout(absl::ZeroDuration())); | |
| EXPECT_EQ(events.size(), 1); | |
| } | |
| TEST(EventQueueThreadTest, PopAllDrainsQueue) { | |
| EventQueue queue; | |
| queue.Push(Event{}); | |
| queue.Push(Event{}); | |
| queue.Push(Event{}); | |
| ASSERT_OK_AND_ASSIGN(auto events, | |
| queue.PopAllWithTimeout(absl::ZeroDuration())); | |
| EXPECT_EQ(events.size(), 3); | |
| // Subsequent pop should be empty. | |
| ASSERT_OK_AND_ASSIGN(auto empty_events, | |
| queue.PopAllWithTimeout(absl::ZeroDuration())); | |
| EXPECT_TRUE(empty_events.empty()); | |
| } | |
| TEST(EventQueueThreadTest, PopWithTimeoutBlocksUntilEvent) { | |
| EventQueue queue; | |
| std::thread writer_thread([&queue]() { | |
| absl::SleepFor(absl::Milliseconds(50)); | |
| queue.Push(Event{}); | |
| }); | |
| auto start = absl::Now(); | |
| ASSERT_OK_AND_ASSIGN(auto events, queue.PopAllWithTimeout(absl::Seconds(2))); | |
| auto duration = absl::Now() - start; | |
| EXPECT_EQ(events.size(), 1); | |
| EXPECT_LT(duration, absl::Seconds(1)); | |
| writer_thread.join(); | |
| } | |
| TEST(EventQueueThreadTest, PopWithTimeoutBlocksUntilClose) { | |
| EventQueue queue; | |
| std::thread writer_thread([&queue]() { | |
| absl::SleepFor(absl::Milliseconds(50)); | |
| queue.Close(); | |
| }); | |
| auto start = absl::Now(); | |
| auto events = queue.PopAllWithTimeout(absl::Seconds(2)); | |
| auto duration = absl::Now() - start; | |
| // It should return error because it was closed and empty. | |
| EXPECT_EQ(events.status().code(), absl::StatusCode::kAborted); | |
| EXPECT_LT(duration, absl::Seconds(1)); | |
| writer_thread.join(); | |
| } | |
| TEST(EventQueueThreadTest, PopWithTimeoutTimesOut) { | |
| EventQueue queue; | |
| ASSERT_OK_AND_ASSIGN(auto events, | |
| queue.PopAllWithTimeout(absl::Milliseconds(10))); | |
| EXPECT_TRUE(events.empty()); | |
| } | |
| TEST(EventQueueThreadTest, PopAfterCloseReturnsError) { | |
| EventQueue queue; | |
| queue.Close(); | |
| auto events = queue.PopAllWithTimeout(absl::ZeroDuration()); | |
| EXPECT_FALSE(events.ok()); | |
| EXPECT_EQ(events.status().code(), absl::StatusCode::kAborted); | |
| } | |
| TEST(EventQueueThreadTest, PopDrainsRemainingEventsAfterClose) { | |
| EventQueue queue; | |
| queue.Push(Event{}); | |
| queue.Close(); | |
| // First pop should succeed and return the pushed event. | |
| ASSERT_OK_AND_ASSIGN(auto first_events, | |
| queue.PopAllWithTimeout(absl::ZeroDuration())); | |
| EXPECT_EQ(first_events.size(), 1); | |
| // Second pop should return error because it is empty and closed. | |
| auto second_events = queue.PopAllWithTimeout(absl::ZeroDuration()); | |
| EXPECT_FALSE(second_events.ok()); | |
| EXPECT_EQ(second_events.status().code(), absl::StatusCode::kAborted); | |
| } | |
| } // namespace | |
| } // namespace safepower_agent |