// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/spdy/buffered_spdy_framer.h"

#include <algorithm>
#include <utility>

#include "base/logging.h"
#include "net/log/net_log_with_source.h"
#include "net/spdy/spdy_test_util_common.h"
#include "testing/platform_test.h"

namespace net {

namespace {

class TestBufferedSpdyVisitor : public BufferedSpdyFramerVisitorInterface {
 public:
  TestBufferedSpdyVisitor()
      : buffered_spdy_framer_(kMaxHeaderListSizeForTest, NetLogWithSource()),
        error_count_(0),
        setting_count_(0),
        headers_frame_count_(0),
        push_promise_frame_count_(0),
        goaway_count_(0),
        altsvc_count_(0),
        header_stream_id_(static_cast<spdy::SpdyStreamId>(-1)),
        promised_stream_id_(static_cast<spdy::SpdyStreamId>(-1)) {}

  void OnError(
      http2::Http2DecoderAdapter::SpdyFramerError spdy_framer_error) override {
    VLOG(1) << "spdy::SpdyFramer Error: " << spdy_framer_error;
    error_count_++;
  }

  void OnStreamError(spdy::SpdyStreamId stream_id,
                     const std::string& description) override {
    VLOG(1) << "spdy::SpdyFramer Error on stream: " << stream_id << " "
            << description;
    error_count_++;
  }

  void OnHeaders(spdy::SpdyStreamId stream_id,
                 bool has_priority,
                 int weight,
                 spdy::SpdyStreamId parent_stream_id,
                 bool exclusive,
                 bool fin,
                 spdy::SpdyHeaderBlock headers) override {
    header_stream_id_ = stream_id;
    headers_frame_count_++;
    headers_ = std::move(headers);
  }

  void OnDataFrameHeader(spdy::SpdyStreamId stream_id,
                         size_t length,
                         bool fin) override {
    ADD_FAILURE() << "Unexpected OnDataFrameHeader call.";
  }

  void OnStreamFrameData(spdy::SpdyStreamId stream_id,
                         const char* data,
                         size_t len) override {
    LOG(FATAL) << "Unexpected OnStreamFrameData call.";
  }

  void OnStreamEnd(spdy::SpdyStreamId stream_id) override {
    LOG(FATAL) << "Unexpected OnStreamEnd call.";
  }

  void OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) override {
    LOG(FATAL) << "Unexpected OnStreamPadding call.";
  }

  void OnSettings() override {}

  void OnSettingsAck() override {}

  void OnSettingsEnd() override {}

  void OnSetting(spdy::SpdySettingsId id, uint32_t value) override {
    setting_count_++;
  }

  void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override {}

  void OnRstStream(spdy::SpdyStreamId stream_id,
                   spdy::SpdyErrorCode error_code) override {}

  void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
                spdy::SpdyErrorCode error_code,
                base::StringPiece debug_data) override {
    goaway_count_++;
    goaway_last_accepted_stream_id_ = last_accepted_stream_id;
    goaway_error_code_ = error_code;
    goaway_debug_data_.assign(debug_data.data(), debug_data.size());
  }

  void OnDataFrameHeader(const spdy::SpdySerializedFrame* frame) {
    LOG(FATAL) << "Unexpected OnDataFrameHeader call.";
  }

  void OnRstStream(const spdy::SpdySerializedFrame& frame) {}
  void OnGoAway(const spdy::SpdySerializedFrame& frame) {}
  void OnPing(const spdy::SpdySerializedFrame& frame) {}
  void OnWindowUpdate(spdy::SpdyStreamId stream_id,
                      int delta_window_size) override {}

  void OnPushPromise(spdy::SpdyStreamId stream_id,
                     spdy::SpdyStreamId promised_stream_id,
                     spdy::SpdyHeaderBlock headers) override {
    header_stream_id_ = stream_id;
    push_promise_frame_count_++;
    promised_stream_id_ = promised_stream_id;
    headers_ = std::move(headers);
  }

  void OnAltSvc(spdy::SpdyStreamId stream_id,
                base::StringPiece origin,
                const spdy::SpdyAltSvcWireFormat::AlternativeServiceVector&
                    altsvc_vector) override {
    altsvc_count_++;
    altsvc_stream_id_ = stream_id;
    origin.CopyToString(&altsvc_origin_);
    altsvc_vector_ = altsvc_vector;
  }

  bool OnUnknownFrame(spdy::SpdyStreamId stream_id,
                      uint8_t frame_type) override {
    return true;
  }

  // Convenience function which runs a framer simulation with particular input.
  void SimulateInFramer(const spdy::SpdySerializedFrame& frame) {
    const char* input_ptr = frame.data();
    size_t input_remaining = frame.size();
    buffered_spdy_framer_.set_visitor(this);
    while (input_remaining > 0 &&
           buffered_spdy_framer_.spdy_framer_error() ==
               http2::Http2DecoderAdapter::SPDY_NO_ERROR) {
      // To make the tests more interesting, we feed random (amd small) chunks
      // into the framer.  This simulates getting strange-sized reads from
      // the socket.
      const size_t kMaxReadSize = 32;
      size_t bytes_read =
          (rand() % std::min(input_remaining, kMaxReadSize)) + 1;
      size_t bytes_processed =
          buffered_spdy_framer_.ProcessInput(input_ptr, bytes_read);
      input_remaining -= bytes_processed;
      input_ptr += bytes_processed;
    }
  }

  BufferedSpdyFramer buffered_spdy_framer_;

  // Counters from the visitor callbacks.
  int error_count_;
  int setting_count_;
  int headers_frame_count_;
  int push_promise_frame_count_;
  int goaway_count_;
  int altsvc_count_;

  // Header block streaming state:
  spdy::SpdyStreamId header_stream_id_;
  spdy::SpdyStreamId promised_stream_id_;

  // Headers from OnHeaders and OnPushPromise for verification.
  spdy::SpdyHeaderBlock headers_;

  // OnGoAway parameters.
  spdy::SpdyStreamId goaway_last_accepted_stream_id_;
  spdy::SpdyErrorCode goaway_error_code_;
  std::string goaway_debug_data_;

  // OnAltSvc parameters.
  spdy::SpdyStreamId altsvc_stream_id_;
  std::string altsvc_origin_;
  spdy::SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector_;
};

}  // namespace

class BufferedSpdyFramerTest : public PlatformTest {};

TEST_F(BufferedSpdyFramerTest, OnSetting) {
  spdy::SpdyFramer framer(spdy::SpdyFramer::ENABLE_COMPRESSION);
  spdy::SpdySettingsIR settings_ir;
  settings_ir.AddSetting(spdy::SETTINGS_INITIAL_WINDOW_SIZE, 2);
  settings_ir.AddSetting(spdy::SETTINGS_MAX_CONCURRENT_STREAMS, 3);
  spdy::SpdySerializedFrame control_frame(
      framer.SerializeSettings(settings_ir));
  TestBufferedSpdyVisitor visitor;

  visitor.SimulateInFramer(control_frame);
  EXPECT_EQ(0, visitor.error_count_);
  EXPECT_EQ(2, visitor.setting_count_);
}

TEST_F(BufferedSpdyFramerTest, HeaderListTooLarge) {
  spdy::SpdyHeaderBlock headers;
  std::string long_header_value(256 * 1024, 'x');
  headers["foo"] = long_header_value;
  spdy::SpdyHeadersIR headers_ir(/*stream_id=*/1, std::move(headers));

  NetLogWithSource net_log;
  BufferedSpdyFramer framer(kMaxHeaderListSizeForTest, net_log);
  spdy::SpdySerializedFrame control_frame = framer.SerializeFrame(headers_ir);

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(control_frame);

  EXPECT_EQ(1, visitor.error_count_);
  EXPECT_EQ(0, visitor.headers_frame_count_);
  EXPECT_EQ(0, visitor.push_promise_frame_count_);
  EXPECT_EQ(spdy::SpdyHeaderBlock(), visitor.headers_);
}

TEST_F(BufferedSpdyFramerTest, ValidHeadersAfterInvalidHeaders) {
  spdy::SpdyHeaderBlock headers;
  headers["invalid"] = "\r\n\r\n";

  spdy::SpdyHeaderBlock headers2;
  headers["alpha"] = "beta";

  SpdyTestUtil spdy_test_util;
  spdy::SpdySerializedFrame headers_frame(
      spdy_test_util.ConstructSpdyReply(1, std::move(headers)));
  spdy::SpdySerializedFrame headers_frame2(
      spdy_test_util.ConstructSpdyReply(2, std::move(headers2)));

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(headers_frame);
  EXPECT_EQ(1, visitor.error_count_);
  EXPECT_EQ(0, visitor.headers_frame_count_);

  visitor.SimulateInFramer(headers_frame2);
  EXPECT_EQ(1, visitor.error_count_);
  EXPECT_EQ(1, visitor.headers_frame_count_);
}

TEST_F(BufferedSpdyFramerTest, ReadHeadersHeaderBlock) {
  spdy::SpdyHeaderBlock headers;
  headers["alpha"] = "beta";
  headers["gamma"] = "delta";
  spdy::SpdyHeadersIR headers_ir(/*stream_id=*/1, headers.Clone());

  NetLogWithSource net_log;
  BufferedSpdyFramer framer(kMaxHeaderListSizeForTest, net_log);
  spdy::SpdySerializedFrame control_frame = framer.SerializeFrame(headers_ir);

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(control_frame);
  EXPECT_EQ(0, visitor.error_count_);
  EXPECT_EQ(1, visitor.headers_frame_count_);
  EXPECT_EQ(0, visitor.push_promise_frame_count_);
  EXPECT_EQ(headers, visitor.headers_);
}

TEST_F(BufferedSpdyFramerTest, ReadPushPromiseHeaderBlock) {
  spdy::SpdyHeaderBlock headers;
  headers["alpha"] = "beta";
  headers["gamma"] = "delta";
  NetLogWithSource net_log;
  BufferedSpdyFramer framer(kMaxHeaderListSizeForTest, net_log);
  spdy::SpdyPushPromiseIR push_promise_ir(
      /*stream_id=*/1, /*promised_stream_id=*/2, headers.Clone());
  spdy::SpdySerializedFrame control_frame =
      framer.SerializeFrame(push_promise_ir);

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(control_frame);
  EXPECT_EQ(0, visitor.error_count_);
  EXPECT_EQ(0, visitor.headers_frame_count_);
  EXPECT_EQ(1, visitor.push_promise_frame_count_);
  EXPECT_EQ(headers, visitor.headers_);
  EXPECT_EQ(1u, visitor.header_stream_id_);
  EXPECT_EQ(2u, visitor.promised_stream_id_);
}

TEST_F(BufferedSpdyFramerTest, GoAwayDebugData) {
  spdy::SpdyGoAwayIR go_ir(/*last_accepted_stream_id=*/2,
                           spdy::ERROR_CODE_FRAME_SIZE_ERROR, "foo");
  NetLogWithSource net_log;
  BufferedSpdyFramer framer(kMaxHeaderListSizeForTest, net_log);
  spdy::SpdySerializedFrame goaway_frame = framer.SerializeFrame(go_ir);

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(goaway_frame);
  EXPECT_EQ(0, visitor.error_count_);
  EXPECT_EQ(1, visitor.goaway_count_);
  EXPECT_EQ(2u, visitor.goaway_last_accepted_stream_id_);
  EXPECT_EQ(spdy::ERROR_CODE_FRAME_SIZE_ERROR, visitor.goaway_error_code_);
  EXPECT_EQ("foo", visitor.goaway_debug_data_);
}

// ALTSVC frame on stream 0 must have an origin.
TEST_F(BufferedSpdyFramerTest, OnAltSvcOnStreamZero) {
  const spdy::SpdyStreamId altsvc_stream_id(0);
  spdy::SpdyAltSvcIR altsvc_ir(altsvc_stream_id);
  spdy::SpdyAltSvcWireFormat::AlternativeService alternative_service(
      "quic", "alternative.example.org", 443, 86400,
      spdy::SpdyAltSvcWireFormat::VersionVector());
  altsvc_ir.add_altsvc(alternative_service);
  const char altsvc_origin[] = "https://www.example.org";
  altsvc_ir.set_origin(altsvc_origin);
  NetLogWithSource net_log;
  BufferedSpdyFramer framer(kMaxHeaderListSizeForTest, net_log);
  spdy::SpdySerializedFrame altsvc_frame(framer.SerializeFrame(altsvc_ir));

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(altsvc_frame);
  EXPECT_EQ(0, visitor.error_count_);
  EXPECT_EQ(1, visitor.altsvc_count_);
  EXPECT_EQ(altsvc_stream_id, visitor.altsvc_stream_id_);
  EXPECT_EQ(altsvc_origin, visitor.altsvc_origin_);
  ASSERT_EQ(1u, visitor.altsvc_vector_.size());
  EXPECT_EQ(alternative_service, visitor.altsvc_vector_[0]);
}

// ALTSVC frame on a non-zero stream must not have an origin.
TEST_F(BufferedSpdyFramerTest, OnAltSvcOnNonzeroStream) {
  const spdy::SpdyStreamId altsvc_stream_id(1);
  spdy::SpdyAltSvcIR altsvc_ir(altsvc_stream_id);
  spdy::SpdyAltSvcWireFormat::AlternativeService alternative_service(
      "quic", "alternative.example.org", 443, 86400,
      spdy::SpdyAltSvcWireFormat::VersionVector());
  altsvc_ir.add_altsvc(alternative_service);
  NetLogWithSource net_log;
  BufferedSpdyFramer framer(kMaxHeaderListSizeForTest, net_log);
  spdy::SpdySerializedFrame altsvc_frame(framer.SerializeFrame(altsvc_ir));

  TestBufferedSpdyVisitor visitor;
  visitor.SimulateInFramer(altsvc_frame);
  EXPECT_EQ(0, visitor.error_count_);
  EXPECT_EQ(1, visitor.altsvc_count_);
  EXPECT_EQ(altsvc_stream_id, visitor.altsvc_stream_id_);
  EXPECT_TRUE(visitor.altsvc_origin_.empty());
  ASSERT_EQ(1u, visitor.altsvc_vector_.size());
  EXPECT_EQ(alternative_service, visitor.altsvc_vector_[0]);
}

}  // namespace net
