blob: 5e0645365ecfb4b3890137c2a38d656c5c053a24 [file] [log] [blame]
QUICHE team02542a22021-03-22 09:00:16 -07001#include "http2/adapter/window_manager.h"
2
3#include <list>
4
QUICHE team02542a22021-03-22 09:00:16 -07005#include "absl/functional/bind_front.h"
QUICHE teamcff6df52021-03-29 11:54:24 -07006#include "http2/test_tools/http2_random.h"
7#include "common/platform/api/quiche_test.h"
QUICHE team81e779d2021-04-15 16:09:56 -07008#include "common/platform/api/quiche_test_helpers.h"
QUICHE team02542a22021-03-22 09:00:16 -07009
10namespace http2 {
11namespace adapter {
QUICHE teamcff6df52021-03-29 11:54:24 -070012namespace test {
QUICHE team02542a22021-03-22 09:00:16 -070013
14// Use the peer to access private vars of WindowManager.
15class WindowManagerPeer {
16 public:
17 explicit WindowManagerPeer(const WindowManager& wm) : wm_(wm) {}
18
19 size_t buffered() {
20 return wm_.buffered_;
21 }
22
23 private:
24 const WindowManager& wm_;
25};
26
QUICHE teamcff6df52021-03-29 11:54:24 -070027namespace {
28
QUICHE team02542a22021-03-22 09:00:16 -070029class WindowManagerTest : public ::testing::Test {
30 protected:
31 WindowManagerTest()
QUICHE teamcff6df52021-03-29 11:54:24 -070032 : wm_(kDefaultLimit, absl::bind_front(&WindowManagerTest::OnCall, this)),
33 peer_(wm_) {}
QUICHE team02542a22021-03-22 09:00:16 -070034
35 void OnCall(size_t s) {
36 call_sequence_.push_back(s);
37 }
38
39 const size_t kDefaultLimit = 32 * 1024 * 3;
40 std::list<size_t> call_sequence_;
41 WindowManager wm_;
42 WindowManagerPeer peer_;
QUICHE teamcff6df52021-03-29 11:54:24 -070043 ::http2::test::Http2Random random_;
QUICHE team02542a22021-03-22 09:00:16 -070044};
45
46// A few no-op calls.
47TEST_F(WindowManagerTest, NoOps) {
48 wm_.SetWindowSizeLimit(kDefaultLimit);
49 wm_.SetWindowSizeLimit(0);
50 wm_.SetWindowSizeLimit(kDefaultLimit);
51 wm_.MarkDataBuffered(0);
52 wm_.MarkDataFlushed(0);
53 EXPECT_TRUE(call_sequence_.empty());
54}
55
56// This test verifies that WindowManager does not notify its listener when data
57// is only buffered, and never flushed.
58TEST_F(WindowManagerTest, DataOnlyBuffered) {
59 size_t total = 0;
60 while (total < kDefaultLimit) {
QUICHE teamcff6df52021-03-29 11:54:24 -070061 size_t s = std::min<size_t>(kDefaultLimit - total, random_.Uniform(1024));
QUICHE team02542a22021-03-22 09:00:16 -070062 total += s;
63 wm_.MarkDataBuffered(s);
64 }
65 EXPECT_THAT(call_sequence_, ::testing::IsEmpty());
66}
67
68// This test verifies that WindowManager does notify its listener when data is
69// buffered and subsequently flushed.
70TEST_F(WindowManagerTest, DataBufferedAndFlushed) {
71 size_t total_buffered = 0;
72 size_t total_flushed = 0;
73 while (call_sequence_.empty()) {
QUICHE teamcff6df52021-03-29 11:54:24 -070074 size_t buffered =
75 std::min<size_t>(kDefaultLimit - total_buffered, random_.Uniform(1024));
QUICHE team02542a22021-03-22 09:00:16 -070076 wm_.MarkDataBuffered(buffered);
77 total_buffered += buffered;
78 EXPECT_TRUE(call_sequence_.empty());
QUICHE teamcff6df52021-03-29 11:54:24 -070079 size_t flushed = random_.Uniform(total_buffered - total_flushed);
QUICHE team02542a22021-03-22 09:00:16 -070080 wm_.MarkDataFlushed(flushed);
81 total_flushed += flushed;
82 }
83 // If WindowManager decided to send an update, at least one third of the
84 // window must have been consumed by buffered data.
85 EXPECT_GE(total_buffered, kDefaultLimit / 3);
86}
87
88// Window manager should avoid window underflow.
89TEST_F(WindowManagerTest, AvoidWindowUnderflow) {
90 EXPECT_EQ(wm_.CurrentWindowSize(), wm_.WindowSizeLimit());
91 // Don't buffer more than the total window!
92 wm_.MarkDataBuffered(wm_.WindowSizeLimit() + 1);
93 EXPECT_EQ(wm_.CurrentWindowSize(), 0);
94}
95
96// Window manager should GFE_BUG and avoid buffered underflow.
97TEST_F(WindowManagerTest, AvoidBufferedUnderflow) {
98 EXPECT_EQ(peer_.buffered(), 0);
99 // Don't flush more than has been buffered!
QUICHE team81e779d2021-04-15 16:09:56 -0700100 EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(1), "buffered underflow");
QUICHE team02542a22021-03-22 09:00:16 -0700101 EXPECT_EQ(peer_.buffered(), 0);
102
103 wm_.MarkDataBuffered(42);
104 EXPECT_EQ(peer_.buffered(), 42);
105 // Don't flush more than has been buffered!
QUICHE team81e779d2021-04-15 16:09:56 -0700106 EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(43), "buffered underflow");
QUICHE team02542a22021-03-22 09:00:16 -0700107 EXPECT_EQ(peer_.buffered(), 0);
108}
109
110// This test verifies that WindowManager notifies its listener when window is
111// consumed (data is ignored or immediately dropped).
112TEST_F(WindowManagerTest, WindowConsumed) {
113 size_t consumed = kDefaultLimit / 3 - 1;
114 wm_.MarkWindowConsumed(consumed);
115 EXPECT_TRUE(call_sequence_.empty());
116 const size_t extra = 1;
117 wm_.MarkWindowConsumed(extra);
118 EXPECT_THAT(call_sequence_, testing::ElementsAre(consumed + extra));
119}
120
121// This test verifies that WindowManager notifies its listener when the window
122// size limit is increased.
123TEST_F(WindowManagerTest, ListenerCalledOnSizeUpdate) {
124 wm_.SetWindowSizeLimit(kDefaultLimit - 1024);
125 EXPECT_TRUE(call_sequence_.empty());
126 wm_.SetWindowSizeLimit(kDefaultLimit * 5);
127 // Because max(outstanding window, previous limit) is kDefaultLimit, it is
128 // only appropriate to increase the window by kDefaultLimit * 4.
129 EXPECT_THAT(call_sequence_, testing::ElementsAre(kDefaultLimit * 4));
130}
131
132// This test verifies that when data is buffered and then the limit is
133// decreased, WindowManager only notifies the listener once any outstanding
134// window has been consumed.
135TEST_F(WindowManagerTest, WindowUpdateAfterLimitDecreased) {
136 wm_.MarkDataBuffered(kDefaultLimit - 1024);
137 wm_.SetWindowSizeLimit(kDefaultLimit - 2048);
138
139 // Now there are 2048 bytes of window outstanding beyond the current limit,
140 // and we have 1024 bytes of data buffered beyond the current limit. This is
141 // intentional, to be sure that WindowManager works properly if the limit is
142 // decreased at runtime.
143
144 wm_.MarkDataFlushed(512);
145 EXPECT_TRUE(call_sequence_.empty());
146 wm_.MarkDataFlushed(512);
147 EXPECT_TRUE(call_sequence_.empty());
148 wm_.MarkDataFlushed(512);
149 EXPECT_TRUE(call_sequence_.empty());
150 wm_.MarkDataFlushed(1024);
151 EXPECT_THAT(call_sequence_, testing::ElementsAre(512));
152}
153
154// For normal behavior, we only call MaybeNotifyListener() when data is
155// flushed. But if window runs out entirely, we still need to call
156// MaybeNotifyListener() to avoid becoming artificially blocked when data isn't
157// being flushed.
158TEST_F(WindowManagerTest, ZeroWindowNotification) {
159 // Consume a byte of window, but not enough to trigger an update.
160 wm_.MarkWindowConsumed(1);
161
162 // Buffer the remaining window.
163 wm_.MarkDataBuffered(kDefaultLimit - 1);
164 // Listener is notified of the remaining byte of possible window.
165 EXPECT_THAT(call_sequence_, testing::ElementsAre(1));
166}
167
QUICHE teamcff6df52021-03-29 11:54:24 -0700168} // namespace
169} // namespace test
QUICHE team02542a22021-03-22 09:00:16 -0700170} // namespace adapter
171} // namespace http2