#include "http2/adapter/window_manager.h"

#include <list>

#include "absl/functional/bind_front.h"
#include "http2/test_tools/http2_random.h"
#include "common/platform/api/quiche_test.h"
#include "common/platform/api/quiche_test_helpers.h"

namespace http2 {
namespace adapter {
namespace test {

// Use the peer to access private vars of WindowManager.
class WindowManagerPeer {
 public:
  explicit WindowManagerPeer(const WindowManager& wm) : wm_(wm) {}

  int64_t buffered() { return wm_.buffered_; }

 private:
  const WindowManager& wm_;
};

namespace {

class WindowManagerTest : public ::testing::Test {
 protected:
  WindowManagerTest()
      : wm_(kDefaultLimit, absl::bind_front(&WindowManagerTest::OnCall, this)),
        peer_(wm_) {}

  void OnCall(int64_t s) { call_sequence_.push_back(s); }

  const int64_t kDefaultLimit = 32 * 1024 * 3;
  std::list<int64_t> call_sequence_;
  WindowManager wm_;
  WindowManagerPeer peer_;
  ::http2::test::Http2Random random_;
};

// A few no-op calls.
TEST_F(WindowManagerTest, NoOps) {
  wm_.SetWindowSizeLimit(kDefaultLimit);
  wm_.SetWindowSizeLimit(0);
  wm_.SetWindowSizeLimit(kDefaultLimit);
  wm_.MarkDataBuffered(0);
  wm_.MarkDataFlushed(0);
  EXPECT_TRUE(call_sequence_.empty());
}

// This test verifies that WindowManager does not notify its listener when data
// is only buffered, and never flushed.
TEST_F(WindowManagerTest, DataOnlyBuffered) {
  int64_t total = 0;
  while (total < kDefaultLimit) {
    int64_t s = std::min<int64_t>(kDefaultLimit - total, random_.Uniform(1024));
    total += s;
    wm_.MarkDataBuffered(s);
  }
  EXPECT_THAT(call_sequence_, ::testing::IsEmpty());
}

// This test verifies that WindowManager does notify its listener when data is
// buffered and subsequently flushed.
TEST_F(WindowManagerTest, DataBufferedAndFlushed) {
  int64_t total_buffered = 0;
  int64_t total_flushed = 0;
  while (call_sequence_.empty()) {
    int64_t buffered = std::min<int64_t>(kDefaultLimit - total_buffered,
                                         random_.Uniform(1024));
    wm_.MarkDataBuffered(buffered);
    total_buffered += buffered;
    EXPECT_TRUE(call_sequence_.empty());
    int64_t flushed = random_.Uniform(total_buffered - total_flushed);
    wm_.MarkDataFlushed(flushed);
    total_flushed += flushed;
  }
  // If WindowManager decided to send an update, at least one third of the
  // window must have been consumed by buffered data.
  EXPECT_GE(total_buffered, kDefaultLimit / 3);
}

// Window manager should avoid window underflow.
TEST_F(WindowManagerTest, AvoidWindowUnderflow) {
  EXPECT_EQ(wm_.CurrentWindowSize(), wm_.WindowSizeLimit());
  // Don't buffer more than the total window!
  wm_.MarkDataBuffered(wm_.WindowSizeLimit() + 1);
  EXPECT_EQ(wm_.CurrentWindowSize(), 0u);
}

// Window manager should GFE_BUG and avoid buffered underflow.
TEST_F(WindowManagerTest, AvoidBufferedUnderflow) {
  EXPECT_EQ(peer_.buffered(), 0u);
  // Don't flush more than has been buffered!
  EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(1), "buffered underflow");
  EXPECT_EQ(peer_.buffered(), 0u);

  wm_.MarkDataBuffered(42);
  EXPECT_EQ(peer_.buffered(), 42u);
  // Don't flush more than has been buffered!
  EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(43), "buffered underflow");
  EXPECT_EQ(peer_.buffered(), 0u);
}

// This test verifies that WindowManager notifies its listener when window is
// consumed (data is ignored or immediately dropped).
TEST_F(WindowManagerTest, WindowConsumed) {
  int64_t consumed = kDefaultLimit / 3 - 1;
  wm_.MarkWindowConsumed(consumed);
  EXPECT_TRUE(call_sequence_.empty());
  const int64_t extra = 1;
  wm_.MarkWindowConsumed(extra);
  EXPECT_THAT(call_sequence_, testing::ElementsAre(consumed + extra));
}

// This test verifies that WindowManager notifies its listener when the window
// size limit is increased.
TEST_F(WindowManagerTest, ListenerCalledOnSizeUpdate) {
  wm_.SetWindowSizeLimit(kDefaultLimit - 1024);
  EXPECT_TRUE(call_sequence_.empty());
  wm_.SetWindowSizeLimit(kDefaultLimit * 5);
  // Because max(outstanding window, previous limit) is kDefaultLimit, it is
  // only appropriate to increase the window by kDefaultLimit * 4.
  EXPECT_THAT(call_sequence_, testing::ElementsAre(kDefaultLimit * 4));
}

// This test verifies that when data is buffered and then the limit is
// decreased, WindowManager only notifies the listener once any outstanding
// window has been consumed.
TEST_F(WindowManagerTest, WindowUpdateAfterLimitDecreased) {
  wm_.MarkDataBuffered(kDefaultLimit - 1024);
  wm_.SetWindowSizeLimit(kDefaultLimit - 2048);

  // Now there are 2048 bytes of window outstanding beyond the current limit,
  // and we have 1024 bytes of data buffered beyond the current limit. This is
  // intentional, to be sure that WindowManager works properly if the limit is
  // decreased at runtime.

  wm_.MarkDataFlushed(512);
  EXPECT_TRUE(call_sequence_.empty());
  wm_.MarkDataFlushed(512);
  EXPECT_TRUE(call_sequence_.empty());
  wm_.MarkDataFlushed(512);
  EXPECT_TRUE(call_sequence_.empty());
  wm_.MarkDataFlushed(1024);
  EXPECT_THAT(call_sequence_, testing::ElementsAre(512));
}

// For normal behavior, we only call MaybeNotifyListener() when data is
// flushed. But if window runs out entirely, we still need to call
// MaybeNotifyListener() to avoid becoming artificially blocked when data isn't
// being flushed.
TEST_F(WindowManagerTest, ZeroWindowNotification) {
  // Consume a byte of window, but not enough to trigger an update.
  wm_.MarkWindowConsumed(1);

  // Buffer the remaining window.
  wm_.MarkDataBuffered(kDefaultLimit - 1);
  // Listener is notified of the remaining byte of possible window.
  EXPECT_THAT(call_sequence_, testing::ElementsAre(1));
}

TEST_F(WindowManagerTest, OnWindowSizeLimitChange) {
  wm_.MarkDataBuffered(10000);
  EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit - 10000);
  EXPECT_EQ(wm_.WindowSizeLimit(), kDefaultLimit);

  wm_.OnWindowSizeLimitChange(kDefaultLimit + 1000);
  EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit - 9000);
  EXPECT_EQ(wm_.WindowSizeLimit(), kDefaultLimit + 1000);

  wm_.OnWindowSizeLimitChange(kDefaultLimit - 1000);
  EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit - 11000);
  EXPECT_EQ(wm_.WindowSizeLimit(), kDefaultLimit - 1000);
}

TEST_F(WindowManagerTest, NegativeWindowSize) {
  wm_.MarkDataBuffered(80000);
  // 98304 window - 80000 buffered = 18304 available
  EXPECT_EQ(wm_.CurrentWindowSize(), 18304);
  wm_.OnWindowSizeLimitChange(65535);
  // limit decreases by 98304 - 65535 = 32769, window becomes -14465
  EXPECT_EQ(wm_.CurrentWindowSize(), -14465);
  wm_.MarkDataFlushed(70000);
  // Still 10000 bytes buffered, so window manager grants sufficient quota to
  // reach a window of 65535 - 10000.
  EXPECT_EQ(wm_.CurrentWindowSize(), 55535);
  // Desired window minus existing window: 55535 - (-14465) = 70000
  EXPECT_THAT(call_sequence_, testing::ElementsAre(70000));
}

TEST_F(WindowManagerTest, IncreaseWindow) {
  wm_.MarkDataBuffered(1000);
  EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit - 1000);
  EXPECT_EQ(wm_.WindowSizeLimit(), kDefaultLimit);

  // Increasing the window beyond the limit is allowed.
  wm_.IncreaseWindow(5000);
  EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit + 4000);
  EXPECT_EQ(wm_.WindowSizeLimit(), kDefaultLimit);

  // 80000 bytes are buffered, then flushed.
  wm_.MarkWindowConsumed(80000);
  // The window manager replenishes the consumed quota up to the limit.
  EXPECT_THAT(call_sequence_, testing::ElementsAre(75000));
  // The window is the limit, minus buffered data, as expected.
  EXPECT_EQ(wm_.CurrentWindowSize(), kDefaultLimit - 1000);
}

}  // namespace
}  // namespace test
}  // namespace adapter
}  // namespace http2
