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