| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 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 "net/quic/quic_write_blocked_list.h" | |
| 6 | |
| 7 #include "net/quic/test_tools/quic_test_utils.h" | |
| 8 #include "testing/gtest/include/gtest/gtest.h" | |
| 9 | |
| 10 using net::kV3LowestPriority; | |
| 11 using net::kV3HighestPriority; | |
| 12 | |
| 13 namespace net { | |
| 14 namespace test { | |
| 15 namespace { | |
| 16 | |
| 17 TEST(QuicWriteBlockedListTest, PriorityOrder) { | |
| 18 QuicWriteBlockedList write_blocked_list; | |
| 19 | |
| 20 // Mark streams blocked in roughly reverse priority order, and | |
| 21 // verify that streams are sorted. | |
| 22 write_blocked_list.RegisterStream(40, kV3LowestPriority); | |
| 23 write_blocked_list.RegisterStream(23, kV3HighestPriority); | |
| 24 write_blocked_list.RegisterStream(17, kV3HighestPriority); | |
| 25 write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority); | |
| 26 write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority); | |
| 27 | |
| 28 write_blocked_list.AddStream(40); | |
| 29 write_blocked_list.AddStream(23); | |
| 30 write_blocked_list.AddStream(17); | |
| 31 write_blocked_list.AddStream(kHeadersStreamId); | |
| 32 write_blocked_list.AddStream(kCryptoStreamId); | |
| 33 | |
| 34 EXPECT_EQ(5u, write_blocked_list.NumBlockedStreams()); | |
| 35 EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 36 EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams()); | |
| 37 // The Crypto stream is highest priority. | |
| 38 EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront()); | |
| 39 // Followed by the Headers stream. | |
| 40 EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront()); | |
| 41 // Streams with same priority are popped in the order they were inserted. | |
| 42 EXPECT_EQ(23u, write_blocked_list.PopFront()); | |
| 43 EXPECT_EQ(17u, write_blocked_list.PopFront()); | |
| 44 // Low priority stream appears last. | |
| 45 EXPECT_EQ(40u, write_blocked_list.PopFront()); | |
| 46 | |
| 47 EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); | |
| 48 EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 49 EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); | |
| 50 } | |
| 51 | |
| 52 TEST(QuicWriteBlockedListTest, CryptoStream) { | |
| 53 QuicWriteBlockedList write_blocked_list; | |
| 54 write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority); | |
| 55 write_blocked_list.AddStream(kCryptoStreamId); | |
| 56 | |
| 57 EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); | |
| 58 EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 59 EXPECT_EQ(kCryptoStreamId, write_blocked_list.PopFront()); | |
| 60 EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); | |
| 61 EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 62 } | |
| 63 | |
| 64 TEST(QuicWriteBlockedListTest, HeadersStream) { | |
| 65 QuicWriteBlockedList write_blocked_list; | |
| 66 write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority); | |
| 67 write_blocked_list.AddStream(kHeadersStreamId); | |
| 68 | |
| 69 EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); | |
| 70 EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 71 EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront()); | |
| 72 EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); | |
| 73 EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 74 } | |
| 75 | |
| 76 TEST(QuicWriteBlockedListTest, VerifyHeadersStream) { | |
| 77 QuicWriteBlockedList write_blocked_list; | |
| 78 write_blocked_list.RegisterStream(5, kV3HighestPriority); | |
| 79 write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority); | |
| 80 write_blocked_list.AddStream(5); | |
| 81 write_blocked_list.AddStream(kHeadersStreamId); | |
| 82 | |
| 83 EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); | |
| 84 EXPECT_TRUE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 85 EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams()); | |
| 86 // In newer QUIC versions, there is a headers stream which is | |
| 87 // higher priority than data streams. | |
| 88 EXPECT_EQ(kHeadersStreamId, write_blocked_list.PopFront()); | |
| 89 EXPECT_EQ(5u, write_blocked_list.PopFront()); | |
| 90 EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); | |
| 91 EXPECT_FALSE(write_blocked_list.HasWriteBlockedCryptoOrHeadersStream()); | |
| 92 EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); | |
| 93 } | |
| 94 | |
| 95 TEST(QuicWriteBlockedListTest, NoDuplicateEntries) { | |
| 96 // Test that QuicWriteBlockedList doesn't allow duplicate entries. | |
| 97 QuicWriteBlockedList write_blocked_list; | |
| 98 | |
| 99 // Try to add a stream to the write blocked list multiple times at the same | |
| 100 // priority. | |
| 101 const QuicStreamId kBlockedId = kClientDataStreamId1; | |
| 102 write_blocked_list.RegisterStream(kBlockedId, kV3HighestPriority); | |
| 103 write_blocked_list.AddStream(kBlockedId); | |
| 104 write_blocked_list.AddStream(kBlockedId); | |
| 105 write_blocked_list.AddStream(kBlockedId); | |
| 106 | |
| 107 // This should only result in one blocked stream being added. | |
| 108 EXPECT_EQ(1u, write_blocked_list.NumBlockedStreams()); | |
| 109 EXPECT_TRUE(write_blocked_list.HasWriteBlockedDataStreams()); | |
| 110 | |
| 111 // There should only be one stream to pop off the front. | |
| 112 EXPECT_EQ(kBlockedId, write_blocked_list.PopFront()); | |
| 113 EXPECT_EQ(0u, write_blocked_list.NumBlockedStreams()); | |
| 114 EXPECT_FALSE(write_blocked_list.HasWriteBlockedDataStreams()); | |
| 115 } | |
| 116 | |
| 117 TEST(QuicWriteBlockedListTest, BatchingWrites) { | |
| 118 QuicWriteBlockedList write_blocked_list; | |
| 119 | |
| 120 const QuicStreamId id1 = kClientDataStreamId1; | |
| 121 const QuicStreamId id2 = kClientDataStreamId2; | |
| 122 const QuicStreamId id3 = kClientDataStreamId2 + 2; | |
| 123 write_blocked_list.RegisterStream(id1, kV3LowestPriority); | |
| 124 write_blocked_list.RegisterStream(id2, kV3LowestPriority); | |
| 125 write_blocked_list.RegisterStream(id3, kV3HighestPriority); | |
| 126 | |
| 127 write_blocked_list.AddStream(id1); | |
| 128 write_blocked_list.AddStream(id2); | |
| 129 EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); | |
| 130 | |
| 131 // The first stream we push back should stay at the front until 16k is | |
| 132 // written. | |
| 133 EXPECT_EQ(id1, write_blocked_list.PopFront()); | |
| 134 write_blocked_list.UpdateBytesForStream(id1, 15999); | |
| 135 write_blocked_list.AddStream(id1); | |
| 136 EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); | |
| 137 EXPECT_EQ(id1, write_blocked_list.PopFront()); | |
| 138 | |
| 139 // Once 16k is written the first stream will yield to the next. | |
| 140 write_blocked_list.UpdateBytesForStream(id1, 1); | |
| 141 write_blocked_list.AddStream(id1); | |
| 142 EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); | |
| 143 EXPECT_EQ(id2, write_blocked_list.PopFront()); | |
| 144 | |
| 145 // Set the new stream to have written all but one byte. | |
| 146 write_blocked_list.UpdateBytesForStream(id2, 15999); | |
| 147 write_blocked_list.AddStream(id2); | |
| 148 EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); | |
| 149 | |
| 150 // Ensure higher priority streams are popped first. | |
| 151 write_blocked_list.AddStream(id3); | |
| 152 EXPECT_EQ(id3, write_blocked_list.PopFront()); | |
| 153 | |
| 154 // Higher priority streams will always be popped first, even if using their | |
| 155 // byte quota | |
| 156 write_blocked_list.UpdateBytesForStream(id3, 20000); | |
| 157 write_blocked_list.AddStream(id3); | |
| 158 EXPECT_EQ(id3, write_blocked_list.PopFront()); | |
| 159 | |
| 160 // Once the higher priority stream is out of the way, id2 will resume its 16k | |
| 161 // write, with only 1 byte remaining of its guaranteed write allocation. | |
| 162 EXPECT_EQ(id2, write_blocked_list.PopFront()); | |
| 163 write_blocked_list.AddStream(id2); | |
| 164 write_blocked_list.UpdateBytesForStream(id2, 1); | |
| 165 write_blocked_list.AddStream(id2); | |
| 166 EXPECT_EQ(2u, write_blocked_list.NumBlockedStreams()); | |
| 167 EXPECT_EQ(id1, write_blocked_list.PopFront()); | |
| 168 } | |
| 169 | |
| 170 TEST(QuicWriteBlockedListTest, Ceding) { | |
| 171 QuicWriteBlockedList write_blocked_list; | |
| 172 | |
| 173 write_blocked_list.RegisterStream(15, kV3HighestPriority); | |
| 174 write_blocked_list.RegisterStream(16, kV3HighestPriority); | |
| 175 write_blocked_list.RegisterStream(5, 5); | |
| 176 write_blocked_list.RegisterStream(4, 5); | |
| 177 write_blocked_list.RegisterStream(7, 7); | |
| 178 write_blocked_list.RegisterStream(kHeadersStreamId, kV3HighestPriority); | |
| 179 write_blocked_list.RegisterStream(kCryptoStreamId, kV3HighestPriority); | |
| 180 | |
| 181 // When nothing is on the list, nothing yields. | |
| 182 EXPECT_FALSE(write_blocked_list.ShouldYield(5)); | |
| 183 | |
| 184 write_blocked_list.AddStream(5); | |
| 185 // 5 should not yield to itself. | |
| 186 EXPECT_FALSE(write_blocked_list.ShouldYield(5)); | |
| 187 // 4 and 7 are equal or lower priority and should yield to 5. | |
| 188 EXPECT_TRUE(write_blocked_list.ShouldYield(4)); | |
| 189 EXPECT_TRUE(write_blocked_list.ShouldYield(7)); | |
| 190 // 15, headers and crypto should preempt 5. | |
| 191 EXPECT_FALSE(write_blocked_list.ShouldYield(15)); | |
| 192 EXPECT_FALSE(write_blocked_list.ShouldYield(kHeadersStreamId)); | |
| 193 EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId)); | |
| 194 | |
| 195 // Block a high priority stream. | |
| 196 write_blocked_list.AddStream(15); | |
| 197 // 16 should yield (same priority) but headers and crypto will still not. | |
| 198 EXPECT_TRUE(write_blocked_list.ShouldYield(16)); | |
| 199 EXPECT_FALSE(write_blocked_list.ShouldYield(kHeadersStreamId)); | |
| 200 EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId)); | |
| 201 | |
| 202 // Block the headers stream. All streams but crypto and headers should yield. | |
| 203 write_blocked_list.AddStream(kHeadersStreamId); | |
| 204 EXPECT_TRUE(write_blocked_list.ShouldYield(16)); | |
| 205 EXPECT_TRUE(write_blocked_list.ShouldYield(15)); | |
| 206 EXPECT_FALSE(write_blocked_list.ShouldYield(kHeadersStreamId)); | |
| 207 EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId)); | |
| 208 | |
| 209 // Block the crypto stream. All streams but crypto should yield. | |
| 210 write_blocked_list.AddStream(kCryptoStreamId); | |
| 211 EXPECT_TRUE(write_blocked_list.ShouldYield(16)); | |
| 212 EXPECT_TRUE(write_blocked_list.ShouldYield(15)); | |
| 213 EXPECT_TRUE(write_blocked_list.ShouldYield(kHeadersStreamId)); | |
| 214 EXPECT_FALSE(write_blocked_list.ShouldYield(kCryptoStreamId)); | |
| 215 } | |
| 216 | |
| 217 } // namespace | |
| 218 } // namespace test | |
| 219 } // namespace net | |
| OLD | NEW |