| // Copyright (c) 2019 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 "spdy/core/lifo_write_scheduler.h" |
| |
| #include "common/platform/api/quiche_test.h" |
| #include "spdy/core/spdy_protocol.h" |
| #include "spdy/core/spdy_test_utils.h" |
| #include "spdy/platform/api/spdy_test_helpers.h" |
| |
| namespace spdy { |
| |
| namespace test { |
| |
| template <typename StreamIdType> |
| class LifoWriteSchedulerPeer { |
| public: |
| explicit LifoWriteSchedulerPeer(LifoWriteScheduler<StreamIdType>* scheduler) |
| : scheduler_(scheduler) {} |
| |
| size_t NumRegisteredListStreams() const { |
| return scheduler_->registered_streams_.size(); |
| } |
| |
| std::set<StreamIdType>* GetReadyList() const { |
| return &scheduler_->ready_streams_; |
| } |
| |
| private: |
| LifoWriteScheduler<StreamIdType>* scheduler_; |
| }; |
| |
| // Test add and remove from ready list. |
| TEST(LifoWriteSchedulerTest, ReadyListTest) { |
| LifoWriteScheduler<SpdyStreamId> lifo; |
| LifoWriteSchedulerPeer<SpdyStreamId> peer(&lifo); |
| |
| EXPECT_SPDY_BUG( |
| EXPECT_EQ(0u, std::get<0>(lifo.PopNextReadyStreamAndPrecedence())), |
| "No ready streams available"); |
| EXPECT_SPDY_BUG(EXPECT_EQ(0u, lifo.PopNextReadyStream()), |
| "No ready streams available"); |
| EXPECT_FALSE(lifo.HasReadyStreams()); |
| EXPECT_SPDY_BUG(lifo.MarkStreamReady(9, true), "Stream 9 is not registered"); |
| EXPECT_SPDY_BUG(lifo.IsStreamReady(9), "Stream 9 is not registered"); |
| SpdyStreamPrecedence precedence(1); |
| lifo.RegisterStream(3, precedence); |
| EXPECT_FALSE(lifo.IsStreamReady(3)); |
| lifo.RegisterStream(7, precedence); |
| lifo.RegisterStream(9, precedence); |
| lifo.RegisterStream(11, precedence); |
| lifo.RegisterStream(13, precedence); |
| lifo.RegisterStream(15, precedence); |
| lifo.RegisterStream(17, precedence); |
| lifo.MarkStreamReady(9, true); |
| lifo.MarkStreamReady(15, true); |
| lifo.MarkStreamReady(7, true); |
| lifo.MarkStreamReady(13, true); |
| lifo.MarkStreamReady(11, true); |
| lifo.MarkStreamReady(3, true); |
| EXPECT_TRUE(lifo.IsStreamReady(3)); |
| lifo.MarkStreamReady(17, true); |
| EXPECT_TRUE(lifo.HasReadyStreams()); |
| EXPECT_EQ(7u, lifo.NumReadyStreams()); |
| |
| // Verify MarkStream(Not)Ready() can be called multiple times for the same |
| // stream. |
| lifo.MarkStreamReady(11, true); |
| lifo.MarkStreamNotReady(5); |
| lifo.MarkStreamNotReady(21); |
| |
| EXPECT_EQ(17u, lifo.PopNextReadyStream()); |
| EXPECT_EQ(15u, std::get<0>(lifo.PopNextReadyStreamAndPrecedence())); |
| EXPECT_TRUE(lifo.ShouldYield(9)); |
| EXPECT_FALSE(lifo.ShouldYield(13)); |
| EXPECT_FALSE(lifo.ShouldYield(15)); |
| |
| lifo.MarkStreamNotReady(3); |
| EXPECT_TRUE(peer.GetReadyList()->find(3) == peer.GetReadyList()->end()); |
| lifo.MarkStreamNotReady(13); |
| EXPECT_TRUE(peer.GetReadyList()->find(13) == peer.GetReadyList()->end()); |
| lifo.MarkStreamNotReady(7); |
| EXPECT_TRUE(peer.GetReadyList()->find(7) == peer.GetReadyList()->end()); |
| EXPECT_EQ(2u, lifo.NumReadyStreams()); |
| |
| lifo.MarkStreamNotReady(9); |
| lifo.MarkStreamNotReady(11); |
| EXPECT_FALSE(lifo.ShouldYield(1)); |
| } |
| |
| // Test add and remove from registered list. |
| TEST(LifoWriteSchedulerTest, RegisterListTest) { |
| LifoWriteScheduler<SpdyStreamId> lifo; |
| LifoWriteSchedulerPeer<SpdyStreamId> peer(&lifo); |
| SpdyStreamPrecedence precedence(1); |
| EXPECT_EQ(0u, lifo.NumRegisteredStreams()); |
| lifo.RegisterStream(3, precedence); |
| lifo.RegisterStream(5, precedence); |
| lifo.RegisterStream(7, precedence); |
| lifo.RegisterStream(9, precedence); |
| lifo.RegisterStream(11, precedence); |
| EXPECT_EQ(5u, lifo.NumRegisteredStreams()); |
| |
| EXPECT_TRUE(lifo.StreamRegistered(3)); |
| EXPECT_TRUE(lifo.StreamRegistered(5)); |
| EXPECT_TRUE(lifo.StreamRegistered(7)); |
| EXPECT_TRUE(lifo.StreamRegistered(9)); |
| EXPECT_TRUE(lifo.StreamRegistered(11)); |
| EXPECT_SPDY_BUG(lifo.RegisterStream(11, precedence), |
| "Stream 11 already registered"); |
| EXPECT_EQ(5u, peer.NumRegisteredListStreams()); |
| |
| lifo.UnregisterStream(3); |
| EXPECT_EQ(4u, lifo.NumRegisteredStreams()); |
| EXPECT_FALSE(lifo.StreamRegistered(3)); |
| EXPECT_SPDY_BUG(lifo.UnregisterStream(3), "Stream 3 is not registered"); |
| EXPECT_SPDY_BUG(lifo.UnregisterStream(13), "Stream 13 is not registered"); |
| lifo.UnregisterStream(11); |
| EXPECT_FALSE(lifo.StreamRegistered(11)); |
| lifo.UnregisterStream(7); |
| EXPECT_EQ(2u, lifo.NumRegisteredStreams()); |
| EXPECT_FALSE(lifo.StreamRegistered(7)); |
| EXPECT_TRUE(lifo.StreamRegistered(5)); |
| EXPECT_TRUE(lifo.StreamRegistered(9)); |
| } |
| |
| // Test mark latest event time. |
| TEST(LifoWriteSchedulerTest, GetLatestEventTest) { |
| LifoWriteScheduler<SpdyStreamId> lifo; |
| LifoWriteSchedulerPeer<SpdyStreamId> peer(&lifo); |
| SpdyStreamPrecedence precedence(1); |
| lifo.RegisterStream(1, precedence); |
| lifo.RegisterStream(3, precedence); |
| lifo.RegisterStream(5, precedence); |
| lifo.RegisterStream(7, precedence); |
| lifo.RegisterStream(9, precedence); |
| lifo.RecordStreamEventTime(1, 1); |
| lifo.RecordStreamEventTime(3, 8); |
| lifo.RecordStreamEventTime(5, 4); |
| lifo.RecordStreamEventTime(7, 2); |
| lifo.RecordStreamEventTime(9, 3); |
| EXPECT_SPDY_BUG(lifo.RecordStreamEventTime(11, 1), |
| "Stream 11 is not registered"); |
| EXPECT_EQ(0, lifo.GetLatestEventWithPrecedence(9)); |
| EXPECT_EQ(3, lifo.GetLatestEventWithPrecedence(7)); |
| EXPECT_EQ(3, lifo.GetLatestEventWithPrecedence(5)); |
| EXPECT_EQ(4, lifo.GetLatestEventWithPrecedence(3)); |
| EXPECT_EQ(8, lifo.GetLatestEventWithPrecedence(1)); |
| EXPECT_SPDY_BUG(lifo.GetLatestEventWithPrecedence(11), |
| "Stream 11 is not registered"); |
| } |
| |
| TEST(LifoWriteSchedulerTest, GetStreamPrecedence) { |
| LifoWriteScheduler<SpdyStreamId> lifo; |
| // Return lowest priority for unknown stream. |
| EXPECT_EQ(kV3LowestPriority, lifo.GetStreamPrecedence(1).spdy3_priority()); |
| |
| lifo.RegisterStream(1, SpdyStreamPrecedence(3)); |
| EXPECT_TRUE(lifo.GetStreamPrecedence(1).is_spdy3_priority()); |
| EXPECT_EQ(3, lifo.GetStreamPrecedence(1).spdy3_priority()); |
| |
| // Redundant registration shouldn't change stream priority. |
| EXPECT_SPDY_BUG(lifo.RegisterStream(1, SpdyStreamPrecedence(4)), |
| "Stream 1 already registered"); |
| EXPECT_EQ(3, lifo.GetStreamPrecedence(1).spdy3_priority()); |
| |
| lifo.UpdateStreamPrecedence(1, SpdyStreamPrecedence(5)); |
| EXPECT_EQ(5, lifo.GetStreamPrecedence(1).spdy3_priority()); |
| } |
| |
| } // namespace test |
| |
| } // namespace spdy |