| // Copyright 2022 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "quiche/quic/bindings/quic_libevent.h" |
| |
| #include <memory> |
| |
| #include "absl/memory/memory.h" |
| #include "absl/time/clock.h" |
| #include "absl/time/time.h" |
| #include "quiche/quic/core/quic_alarm.h" |
| #include "quiche/quic/core/quic_default_clock.h" |
| #include "quiche/quic/platform/api/quic_test.h" |
| #include "quiche/quic/platform/api/quic_thread.h" |
| |
| namespace quic::test { |
| namespace { |
| |
| class FailureAlarmDelegate : public QuicAlarm::Delegate { |
| public: |
| QuicConnectionContext* GetConnectionContext() override { return nullptr; } |
| void OnAlarm() override { ADD_FAILURE() << "Test timed out"; } |
| }; |
| |
| class LoopBreakThread : public QuicThread { |
| public: |
| LoopBreakThread(LibeventQuicEventLoop* loop) |
| : QuicThread("LoopBreakThread"), loop_(loop) {} |
| |
| void Run() override { |
| // Make sure the other thread has actually made the blocking poll/epoll/etc |
| // call before calling WakeUp(). |
| absl::SleepFor(absl::Milliseconds(250)); |
| |
| loop_broken_.store(true); |
| loop_->WakeUp(); |
| } |
| |
| std::atomic<int>& loop_broken() { return loop_broken_; } |
| |
| private: |
| LibeventQuicEventLoop* loop_; |
| std::atomic<int> loop_broken_ = 0; |
| }; |
| |
| TEST(QuicLibeventTest, WakeUpFromAnotherThread) { |
| QuicClock* clock = QuicDefaultClock::Get(); |
| auto event_loop_owned = QuicLibeventEventLoopFactory::Get()->Create(clock); |
| LibeventQuicEventLoop* event_loop = |
| static_cast<LibeventQuicEventLoop*>(event_loop_owned.get()); |
| std::unique_ptr<QuicAlarmFactory> alarm_factory = |
| event_loop->CreateAlarmFactory(); |
| std::unique_ptr<QuicAlarm> timeout_alarm = |
| absl::WrapUnique(alarm_factory->CreateAlarm(new FailureAlarmDelegate())); |
| |
| const QuicTime kTimeoutAt = clock->Now() + QuicTime::Delta::FromSeconds(10); |
| timeout_alarm->Set(kTimeoutAt); |
| |
| LoopBreakThread thread(event_loop); |
| thread.Start(); |
| event_loop->RunEventLoopOnce(QuicTime::Delta::FromSeconds(5 * 60)); |
| EXPECT_TRUE(thread.loop_broken().load()); |
| thread.Join(); |
| } |
| |
| } // namespace |
| } // namespace quic::test |