| #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 |