TestWebTransportFlowControl.cpp (7954B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "TestCommon.h" 7 #include "gtest/gtest.h" 8 #include "WebTransportFlowControl.h" 9 #include "Capsule.h" 10 #include "CapsuleEncoder.h" 11 #include "CapsuleParser.h" 12 13 using namespace mozilla; 14 using namespace mozilla::net; 15 16 TEST(SenderFlowControlTest, BlockedAtZero) 17 { 18 SenderFlowControlBase fc(0); 19 fc.Blocked(); 20 EXPECT_EQ(*fc.BlockedNeeded(), 0u); 21 } 22 23 TEST(SenderFlowControlTest, Blocked) 24 { 25 SenderFlowControlBase fc(10); 26 fc.Blocked(); 27 EXPECT_EQ(*fc.BlockedNeeded(), 10u); 28 } 29 30 TEST(SenderFlowControlTest, UpdateConsume) 31 { 32 SenderFlowControlBase fc(10); 33 fc.Consume(10); 34 EXPECT_EQ(fc.Available(), 0u); 35 fc.Update(5); 36 EXPECT_EQ(fc.Available(), 0u); 37 fc.Update(15); 38 EXPECT_EQ(fc.Available(), 5u); 39 fc.Consume(3); 40 EXPECT_EQ(fc.Available(), 2u); 41 } 42 43 TEST(SenderFlowControlTest, UpdateClearsBlocked) 44 { 45 SenderFlowControlBase fc(10); 46 fc.Blocked(); 47 EXPECT_EQ(*fc.BlockedNeeded(), 10u); 48 fc.Update(5); 49 EXPECT_EQ(*fc.BlockedNeeded(), 10u); 50 fc.Update(11); 51 EXPECT_EQ(fc.BlockedNeeded(), Nothing()); 52 } 53 54 TEST(LocalStreamLimitsTest, StreamIdAllocation) 55 { 56 LocalStreamLimits fc; 57 fc[WebTransportStreamType::BiDi].Update(2); 58 fc[WebTransportStreamType::UniDi].Update(1); 59 60 // Add streams 61 EXPECT_EQ(*fc.TakeStreamId(WebTransportStreamType::BiDi), StreamId(0u)); 62 EXPECT_EQ(*fc.TakeStreamId(WebTransportStreamType::BiDi), StreamId(4u)); 63 EXPECT_TRUE(fc.TakeStreamId(WebTransportStreamType::BiDi).isNothing()); 64 EXPECT_EQ(*fc.TakeStreamId(WebTransportStreamType::UniDi), StreamId(2u)); 65 EXPECT_TRUE(fc.TakeStreamId(WebTransportStreamType::UniDi).isNothing()); 66 67 auto encoder = fc[WebTransportStreamType::BiDi].CreateStreamsBlockedCapsule(); 68 EXPECT_TRUE(encoder.isSome()); 69 70 auto extractLimitFromEncoder = [](CapsuleEncoder& encoder) -> uint64_t { 71 auto buffer = encoder.GetBuffer(); 72 RefPtr<CapsuleParserListener> listener = new CapsuleParserListener(); 73 UniquePtr<CapsuleParser> parser = MakeUnique<CapsuleParser>(listener); 74 parser->ProcessCapsuleData(buffer.Elements(), buffer.Length()); 75 nsTArray<Capsule> parsed = listener->GetParsedCapsules(); 76 WebTransportStreamsBlockedCapsule blocked = 77 parsed[0].GetWebTransportStreamsBlockedCapsule(); 78 return blocked.mLimit; 79 }; 80 81 EXPECT_EQ(extractLimitFromEncoder(*encoder), 2u); 82 83 // Increase limit 84 fc[WebTransportStreamType::BiDi].Update(3); 85 fc[WebTransportStreamType::UniDi].Update(2); 86 EXPECT_EQ(*fc.TakeStreamId(WebTransportStreamType::BiDi), StreamId(8u)); 87 EXPECT_TRUE(fc.TakeStreamId(WebTransportStreamType::BiDi).isNothing()); 88 EXPECT_EQ(*fc.TakeStreamId(WebTransportStreamType::UniDi), StreamId(6u)); 89 EXPECT_TRUE(fc.TakeStreamId(WebTransportStreamType::UniDi).isNothing()); 90 91 auto encoder1 = 92 fc[WebTransportStreamType::UniDi].CreateStreamsBlockedCapsule(); 93 EXPECT_TRUE(encoder1.isSome()); 94 EXPECT_EQ(extractLimitFromEncoder(*encoder1), 2u); 95 96 auto encoder2 = 97 fc[WebTransportStreamType::BiDi].CreateStreamsBlockedCapsule(); 98 EXPECT_TRUE(encoder2.isSome()); 99 EXPECT_EQ(extractLimitFromEncoder(*encoder2), 3u); 100 } 101 102 TEST(ReceiverFlowControlTest, NoNeedMaxAllowedFrameAtStart) 103 { 104 ReceiverFlowControlBase fc(0); 105 EXPECT_FALSE(fc.CapsuleNeeded()); 106 } 107 108 TEST(ReceiverFlowControlTest, MaxAllowedAfterItemsRetired) 109 { 110 ReceiverFlowControlBase fc(100); 111 fc.Retire(49); 112 EXPECT_FALSE(fc.CapsuleNeeded()); 113 fc.Retire(51); 114 EXPECT_TRUE(fc.CapsuleNeeded()); 115 EXPECT_EQ(fc.NextLimit(), 151u); 116 } 117 118 TEST(ReceiverFlowControlTest, ForceSendMaxAllowed) 119 { 120 ReceiverFlowControlBase fc(100); 121 fc.Retire(10); 122 EXPECT_FALSE(fc.CapsuleNeeded()); 123 } 124 125 TEST(ReceiverFlowControlTest, MultipleRetriesAfterFramePendingIsSet) 126 { 127 ReceiverFlowControlBase fc(100); 128 fc.Retire(51); 129 EXPECT_TRUE(fc.CapsuleNeeded()); 130 EXPECT_EQ(fc.NextLimit(), 151u); 131 fc.Retire(61); 132 EXPECT_TRUE(fc.CapsuleNeeded()); 133 EXPECT_EQ(fc.NextLimit(), 161u); 134 fc.Retire(88); 135 EXPECT_TRUE(fc.CapsuleNeeded()); 136 EXPECT_EQ(fc.NextLimit(), 188u); 137 fc.Retire(90); 138 EXPECT_TRUE(fc.CapsuleNeeded()); 139 EXPECT_EQ(fc.NextLimit(), 190u); 140 fc.CapsuleSent(190); 141 EXPECT_FALSE(fc.CapsuleNeeded()); 142 fc.Retire(141); 143 EXPECT_TRUE(fc.CapsuleNeeded()); 144 EXPECT_EQ(fc.NextLimit(), 241u); 145 fc.CapsuleSent(241); 146 EXPECT_FALSE(fc.CapsuleNeeded()); 147 } 148 149 TEST(ReceiverFlowControlTest, ChangingMaxActive) 150 { 151 ReceiverFlowControlBase fc(100); 152 fc.SetMaxActive(50); 153 EXPECT_FALSE(fc.CapsuleNeeded()); 154 fc.Retire(60); 155 EXPECT_FALSE(fc.CapsuleNeeded()); 156 fc.Retire(76); 157 EXPECT_TRUE(fc.CapsuleNeeded()); 158 EXPECT_EQ(fc.NextLimit(), 126u); 159 fc.SetMaxActive(60); 160 EXPECT_TRUE(fc.CapsuleNeeded()); 161 EXPECT_EQ(fc.NextLimit(), 136u); 162 fc.Retire(136); 163 EXPECT_TRUE(fc.CapsuleNeeded()); 164 EXPECT_EQ(fc.NextLimit(), 196u); 165 } 166 167 TEST(RemoteStreamLimitsTest, HandlesStreamLimitLogicWithRawIds) 168 { 169 RemoteStreamLimits fc(/*bidi=*/2, /*unidi=*/1); 170 171 StreamId bidi0(1); // Stream 0 (BiDi, server-initiated) 172 StreamId bidi1(5); // Stream 1 173 StreamId bidi2(9); // Stream 2 174 StreamId bidi3(13); // Stream 3 175 176 StreamId uni0(3); // Stream 0 (UniDi, server-initiated) 177 StreamId uni1(7); // Stream 1 178 StreamId uni2(11); // Stream 2 179 180 // Initial streams should be allowed 181 EXPECT_TRUE(fc[WebTransportStreamType::BiDi].IsNewStream(bidi0).unwrap()); 182 EXPECT_TRUE(fc[WebTransportStreamType::BiDi].IsNewStream(bidi1).unwrap()); 183 EXPECT_TRUE(fc[WebTransportStreamType::UniDi].IsNewStream(uni0).unwrap()); 184 185 // Exceed limits 186 EXPECT_EQ(fc[WebTransportStreamType::BiDi].IsNewStream(bidi2).unwrapErr(), 187 NS_ERROR_NOT_AVAILABLE); 188 EXPECT_EQ(fc[WebTransportStreamType::UniDi].IsNewStream(uni1).unwrapErr(), 189 NS_ERROR_NOT_AVAILABLE); 190 191 // Take stream IDs 192 EXPECT_EQ(fc[WebTransportStreamType::BiDi].TakeStreamId(), bidi0); 193 EXPECT_EQ(fc[WebTransportStreamType::BiDi].TakeStreamId(), bidi1); 194 EXPECT_EQ(fc[WebTransportStreamType::UniDi].TakeStreamId(), uni0); 195 196 // Retire and allow new BiDi stream 197 fc[WebTransportStreamType::BiDi].FlowControl().AddRetired(1); 198 fc[WebTransportStreamType::BiDi].FlowControl().SendFlowControlUpdate(); 199 200 // Send MaxStreams capsule 201 auto encoder = 202 fc[WebTransportStreamType::BiDi].FlowControl().CreateMaxStreamsCapsule(); 203 EXPECT_TRUE(encoder.isSome()); 204 205 auto extractLimitFromEncoder = [](CapsuleEncoder& encoder) -> uint64_t { 206 auto buffer = encoder.GetBuffer(); 207 RefPtr<CapsuleParserListener> listener = new CapsuleParserListener(); 208 UniquePtr<CapsuleParser> parser = MakeUnique<CapsuleParser>(listener); 209 parser->ProcessCapsuleData(buffer.Elements(), buffer.Length()); 210 nsTArray<Capsule> parsed = listener->GetParsedCapsules(); 211 WebTransportMaxStreamsCapsule maxStreams = 212 parsed[0].GetWebTransportMaxStreamsCapsule(); 213 return maxStreams.mLimit; 214 }; 215 EXPECT_EQ(extractLimitFromEncoder(*encoder), 3u); 216 217 EXPECT_TRUE(fc[WebTransportStreamType::BiDi].IsNewStream(bidi2).unwrap()); 218 EXPECT_EQ(fc[WebTransportStreamType::BiDi].TakeStreamId(), bidi2); 219 220 EXPECT_EQ(fc[WebTransportStreamType::BiDi].IsNewStream(bidi3).unwrapErr(), 221 NS_ERROR_NOT_AVAILABLE); 222 223 // Retire and allow new UniDi stream 224 fc[WebTransportStreamType::UniDi].FlowControl().AddRetired(1); 225 fc[WebTransportStreamType::UniDi].FlowControl().SendFlowControlUpdate(); 226 227 auto encoder1 = 228 fc[WebTransportStreamType::UniDi].FlowControl().CreateMaxStreamsCapsule(); 229 EXPECT_TRUE(encoder1.isSome()); 230 EXPECT_EQ(extractLimitFromEncoder(*encoder1), 2u); 231 232 EXPECT_TRUE(fc[WebTransportStreamType::UniDi].IsNewStream(uni1).unwrap()); 233 EXPECT_EQ(fc[WebTransportStreamType::UniDi].TakeStreamId(), uni1); 234 235 EXPECT_EQ(fc[WebTransportStreamType::UniDi].IsNewStream(uni2).unwrapErr(), 236 NS_ERROR_NOT_AVAILABLE); 237 }