tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }