1 // Copyright 2022 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "quiche/quic/bindings/quic_libevent.h" 6 7 #include <memory> 8 9 #include "absl/memory/memory.h" 10 #include "absl/time/clock.h" 11 #include "absl/time/time.h" 12 #include "quiche/quic/core/quic_alarm.h" 13 #include "quiche/quic/core/quic_default_clock.h" 14 #include "quiche/quic/platform/api/quic_test.h" 15 #include "quiche/quic/platform/api/quic_thread.h" 16 17 namespace quic::test { 18 namespace { 19 20 class FailureAlarmDelegate : public QuicAlarm::Delegate { 21 public: GetConnectionContext()22 QuicConnectionContext* GetConnectionContext() override { return nullptr; } OnAlarm()23 void OnAlarm() override { ADD_FAILURE() << "Test timed out"; } 24 }; 25 26 class LoopBreakThread : public QuicThread { 27 public: LoopBreakThread(LibeventQuicEventLoop * loop)28 LoopBreakThread(LibeventQuicEventLoop* loop) 29 : QuicThread("LoopBreakThread"), loop_(loop) {} 30 Run()31 void Run() override { 32 // Make sure the other thread has actually made the blocking poll/epoll/etc 33 // call before calling WakeUp(). 34 absl::SleepFor(absl::Milliseconds(250)); 35 36 loop_broken_.store(true); 37 loop_->WakeUp(); 38 } 39 loop_broken()40 std::atomic<int>& loop_broken() { return loop_broken_; } 41 42 private: 43 LibeventQuicEventLoop* loop_; 44 std::atomic<int> loop_broken_ = 0; 45 }; 46 TEST(QuicLibeventTest,WakeUpFromAnotherThread)47TEST(QuicLibeventTest, WakeUpFromAnotherThread) { 48 QuicClock* clock = QuicDefaultClock::Get(); 49 auto event_loop_owned = QuicLibeventEventLoopFactory::Get()->Create(clock); 50 LibeventQuicEventLoop* event_loop = 51 static_cast<LibeventQuicEventLoop*>(event_loop_owned.get()); 52 std::unique_ptr<QuicAlarmFactory> alarm_factory = 53 event_loop->CreateAlarmFactory(); 54 std::unique_ptr<QuicAlarm> timeout_alarm = 55 absl::WrapUnique(alarm_factory->CreateAlarm(new FailureAlarmDelegate())); 56 57 const QuicTime kTimeoutAt = clock->Now() + QuicTime::Delta::FromSeconds(10); 58 timeout_alarm->Set(kTimeoutAt); 59 60 LoopBreakThread thread(event_loop); 61 thread.Start(); 62 event_loop->RunEventLoopOnce(QuicTime::Delta::FromSeconds(5 * 60)); 63 EXPECT_TRUE(thread.loop_broken().load()); 64 thread.Join(); 65 } 66 67 } // namespace 68 } // namespace quic::test 69