#include <memory>
#include <string>
#include <vector>

#include "quiche/http2/adapter/http2_protocol.h"
#include "quiche/http2/adapter/nghttp2_adapter.h"
#include "quiche/http2/adapter/oghttp2_adapter.h"
#include "quiche/http2/adapter/recording_http2_visitor.h"
#include "quiche/http2/adapter/test_frame_sequence.h"
#include "quiche/common/platform/api/quiche_test.h"
#include "quiche/spdy/core/spdy_protocol.h"

namespace http2 {
namespace adapter {
namespace test {
namespace {

TEST(AdapterImplComparisonTest, ClientHandlesFrames) {
  RecordingHttp2Visitor nghttp2_visitor;
  std::unique_ptr<NgHttp2Adapter> nghttp2_adapter =
      NgHttp2Adapter::CreateClientAdapter(nghttp2_visitor);

  RecordingHttp2Visitor oghttp2_visitor;
  OgHttp2Adapter::Options options;
  options.perspective = Perspective::kClient;
  std::unique_ptr<OgHttp2Adapter> oghttp2_adapter =
      OgHttp2Adapter::Create(oghttp2_visitor, options);

  const std::string initial_frames = TestFrameSequence()
                                         .ServerPreface()
                                         .Ping(42)
                                         .WindowUpdate(0, 1000)
                                         .Serialize();

  nghttp2_adapter->ProcessBytes(initial_frames);
  oghttp2_adapter->ProcessBytes(initial_frames);

  EXPECT_EQ(nghttp2_visitor.GetEventSequence(),
            oghttp2_visitor.GetEventSequence());

  // TODO(b/181586191): Consider consistent behavior for delivering events on
  // non-existent streams between nghttp2_adapter and oghttp2_adapter.
}

TEST(AdapterImplComparisonTest, SubmitWindowUpdateBumpsWindow) {
  RecordingHttp2Visitor nghttp2_visitor;
  std::unique_ptr<NgHttp2Adapter> nghttp2_adapter =
      NgHttp2Adapter::CreateClientAdapter(nghttp2_visitor);

  RecordingHttp2Visitor oghttp2_visitor;
  OgHttp2Adapter::Options options;
  options.perspective = Perspective::kClient;
  std::unique_ptr<OgHttp2Adapter> oghttp2_adapter =
      OgHttp2Adapter::Create(oghttp2_visitor, options);

  int result;

  const std::vector<Header> request_headers =
      ToHeaders({{":method", "POST"},
                 {":scheme", "https"},
                 {":authority", "example.com"},
                 {":path", "/"}});
  const int kInitialFlowControlWindow = 65535;
  const int kConnectionWindowIncrease = 192 * 1024;

  const int32_t nghttp2_stream_id =
      nghttp2_adapter->SubmitRequest(request_headers, nullptr, true, nullptr);

  // Both the connection and stream flow control windows are increased.
  nghttp2_adapter->SubmitWindowUpdate(0, kConnectionWindowIncrease);
  nghttp2_adapter->SubmitWindowUpdate(nghttp2_stream_id,
                                      kConnectionWindowIncrease);
  result = nghttp2_adapter->Send();
  EXPECT_EQ(0, result);
  int nghttp2_window = nghttp2_adapter->GetReceiveWindowSize();
  EXPECT_EQ(kInitialFlowControlWindow + kConnectionWindowIncrease,
            nghttp2_window);

  const int32_t oghttp2_stream_id =
      oghttp2_adapter->SubmitRequest(request_headers, nullptr, true, nullptr);
  // Both the connection and stream flow control windows are increased.
  oghttp2_adapter->SubmitWindowUpdate(0, kConnectionWindowIncrease);
  oghttp2_adapter->SubmitWindowUpdate(oghttp2_stream_id,
                                      kConnectionWindowIncrease);
  result = oghttp2_adapter->Send();
  EXPECT_EQ(0, result);
  int oghttp2_window = oghttp2_adapter->GetReceiveWindowSize();
  EXPECT_EQ(kInitialFlowControlWindow + kConnectionWindowIncrease,
            oghttp2_window);

  // nghttp2 and oghttp2 agree on the advertised window.
  EXPECT_EQ(nghttp2_window, oghttp2_window);

  ASSERT_EQ(nghttp2_stream_id, oghttp2_stream_id);

  const int kMaxFrameSize = 16 * 1024;
  const std::string body_chunk(kMaxFrameSize, 'a');
  auto sequence = TestFrameSequence();
  sequence.ServerPreface().Headers(nghttp2_stream_id, {{":status", "200"}},
                                   /*fin=*/false);
  // This loop generates enough DATA frames to consume the window increase.
  const int kNumFrames = kConnectionWindowIncrease / kMaxFrameSize;
  for (int i = 0; i < kNumFrames; ++i) {
    sequence.Data(nghttp2_stream_id, body_chunk);
  }
  const std::string frames = sequence.Serialize();

  nghttp2_adapter->ProcessBytes(frames);
  // Marking the data consumed causes a window update, which is reflected in the
  // advertised window size.
  nghttp2_adapter->MarkDataConsumedForStream(nghttp2_stream_id,
                                             kNumFrames * kMaxFrameSize);
  result = nghttp2_adapter->Send();
  EXPECT_EQ(0, result);
  nghttp2_window = nghttp2_adapter->GetReceiveWindowSize();

  oghttp2_adapter->ProcessBytes(frames);
  // Marking the data consumed causes a window update, which is reflected in the
  // advertised window size.
  oghttp2_adapter->MarkDataConsumedForStream(oghttp2_stream_id,
                                             kNumFrames * kMaxFrameSize);
  result = oghttp2_adapter->Send();
  EXPECT_EQ(0, result);
  oghttp2_window = oghttp2_adapter->GetReceiveWindowSize();

  const int kMinExpectation =
      (kInitialFlowControlWindow + kConnectionWindowIncrease) / 2;
  EXPECT_GT(nghttp2_window, kMinExpectation);
  EXPECT_GT(oghttp2_window, kMinExpectation);
}

TEST(AdapterImplComparisonTest, ServerHandlesFrames) {
  RecordingHttp2Visitor nghttp2_visitor;
  std::unique_ptr<NgHttp2Adapter> nghttp2_adapter =
      NgHttp2Adapter::CreateServerAdapter(nghttp2_visitor);

  RecordingHttp2Visitor oghttp2_visitor;
  OgHttp2Adapter::Options options;
  options.perspective = Perspective::kServer;
  std::unique_ptr<OgHttp2Adapter> oghttp2_adapter =
      OgHttp2Adapter::Create(oghttp2_visitor, options);

  const std::string frames = TestFrameSequence()
                                 .ClientPreface()
                                 .Ping(42)
                                 .WindowUpdate(0, 1000)
                                 .Headers(1,
                                          {{":method", "POST"},
                                           {":scheme", "https"},
                                           {":authority", "example.com"},
                                           {":path", "/this/is/request/one"}},
                                          /*fin=*/false)
                                 .WindowUpdate(1, 2000)
                                 .Data(1, "This is the request body.")
                                 .Headers(3,
                                          {{":method", "GET"},
                                           {":scheme", "http"},
                                           {":authority", "example.com"},
                                           {":path", "/this/is/request/two"}},
                                          /*fin=*/true)
                                 .RstStream(3, Http2ErrorCode::CANCEL)
                                 .Ping(47)
                                 .Serialize();

  nghttp2_adapter->ProcessBytes(frames);
  oghttp2_adapter->ProcessBytes(frames);

  EXPECT_EQ(nghttp2_visitor.GetEventSequence(),
            oghttp2_visitor.GetEventSequence());
}

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