// Copyright (c) 2013 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.

#ifndef NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
#define NET_SPDY_SPDY_TEST_UTIL_COMMON_H_

#include <string>
#include <vector>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
#include "net/base/completion_callback.h"
#include "net/base/request_priority.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_info.h"
#include "net/http/http_server_properties_impl.h"
#include "net/http/transport_security_state.h"
#include "net/proxy/proxy_service.h"
#include "net/socket/next_proto.h"
#include "net/socket/socket_test_util.h"
#include "net/spdy/spdy_protocol.h"
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "testing/gtest/include/gtest/gtest.h"

class GURL;

namespace net {

class BoundNetLog;
class SpdySession;
class SpdySessionKey;
class SpdySessionPool;
class SpdyStream;
class SpdyStreamRequest;

// Default upload data used by both, mock objects and framer when creating
// data frames.
const char kDefaultURL[] = "http://www.google.com";
const char kUploadData[] = "hello!";
const int kUploadDataSize = arraysize(kUploadData)-1;

// SpdyNextProtos returns a vector of next protocols for negotiating
// SPDY.
NextProtoVector SpdyNextProtos();

// Chop a frame into an array of MockWrites.
// |data| is the frame to chop.
// |length| is the length of the frame to chop.
// |num_chunks| is the number of chunks to create.
MockWrite* ChopWriteFrame(const char* data, int length, int num_chunks);

// Chop a SpdyFrame into an array of MockWrites.
// |frame| is the frame to chop.
// |num_chunks| is the number of chunks to create.
MockWrite* ChopWriteFrame(const SpdyFrame& frame, int num_chunks);

// Chop a frame into an array of MockReads.
// |data| is the frame to chop.
// |length| is the length of the frame to chop.
// |num_chunks| is the number of chunks to create.
MockRead* ChopReadFrame(const char* data, int length, int num_chunks);

// Chop a SpdyFrame into an array of MockReads.
// |frame| is the frame to chop.
// |num_chunks| is the number of chunks to create.
MockRead* ChopReadFrame(const SpdyFrame& frame, int num_chunks);

// Adds headers and values to a map.
// |extra_headers| is an array of { name, value } pairs, arranged as strings
// where the even entries are the header names, and the odd entries are the
// header values.
// |headers| gets filled in from |extra_headers|.
void AppendToHeaderBlock(const char* const extra_headers[],
                         int extra_header_count,
                         SpdyHeaderBlock* headers);

// Create an async MockWrite from the given SpdyFrame.
MockWrite CreateMockWrite(const SpdyFrame& req);

// Create an async MockWrite from the given SpdyFrame and sequence number.
MockWrite CreateMockWrite(const SpdyFrame& req, int seq);

MockWrite CreateMockWrite(const SpdyFrame& req, int seq, IoMode mode);

// Create a MockRead from the given SpdyFrame.
MockRead CreateMockRead(const SpdyFrame& resp);

// Create a MockRead from the given SpdyFrame and sequence number.
MockRead CreateMockRead(const SpdyFrame& resp, int seq);

MockRead CreateMockRead(const SpdyFrame& resp, int seq, IoMode mode);

// Combines the given SpdyFrames into the given char array and returns
// the total length.
int CombineFrames(const SpdyFrame** frames, int num_frames,
                  char* buff, int buff_len);

// Returns the SpdyPriority embedded in the given frame.  Returns true
// and fills in |priority| on success.
bool GetSpdyPriority(SpdyMajorVersion version,
                     const SpdyFrame& frame,
                     SpdyPriority* priority);

// Tries to create a stream in |session| synchronously. Returns NULL
// on failure.
base::WeakPtr<SpdyStream> CreateStreamSynchronously(
    SpdyStreamType type,
    const base::WeakPtr<SpdySession>& session,
    const GURL& url,
    RequestPriority priority,
    const BoundNetLog& net_log);

// Helper class used by some tests to release a stream as soon as it's
// created.
class StreamReleaserCallback : public TestCompletionCallbackBase {
 public:
  StreamReleaserCallback();

  ~StreamReleaserCallback() override;

  // Returns a callback that releases |request|'s stream.
  CompletionCallback MakeCallback(SpdyStreamRequest* request);

 private:
  void OnComplete(SpdyStreamRequest* request, int result);
};

const size_t kSpdyCredentialSlotUnused = 0;

// This struct holds information used to construct spdy control and data frames.
struct SpdyHeaderInfo {
  SpdyFrameType kind;
  SpdyStreamId id;
  SpdyStreamId assoc_id;
  SpdyPriority priority;
  size_t credential_slot;  // SPDY3 only
  SpdyControlFlags control_flags;
  bool compressed;
  SpdyRstStreamStatus status;
  const char* data;
  uint32 data_length;
  SpdyDataFlags data_flags;
};

// An ECSignatureCreator that returns deterministic signatures.
class MockECSignatureCreator : public crypto::ECSignatureCreator {
 public:
  explicit MockECSignatureCreator(crypto::ECPrivateKey* key);

  // crypto::ECSignatureCreator
  bool Sign(const uint8* data,
            int data_len,
            std::vector<uint8>* signature) override;
  bool DecodeSignature(const std::vector<uint8>& signature,
                       std::vector<uint8>* out_raw_sig) override;

 private:
  crypto::ECPrivateKey* key_;

  DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreator);
};

// An ECSignatureCreatorFactory creates MockECSignatureCreator.
class MockECSignatureCreatorFactory : public crypto::ECSignatureCreatorFactory {
 public:
  MockECSignatureCreatorFactory();
  ~MockECSignatureCreatorFactory() override;

  // crypto::ECSignatureCreatorFactory
  crypto::ECSignatureCreator* Create(crypto::ECPrivateKey* key) override;

 private:
  DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreatorFactory);
};

// Helper to manage the lifetimes of the dependencies for a
// HttpNetworkTransaction.
struct SpdySessionDependencies {
  // Default set of dependencies -- "null" proxy service.
  explicit SpdySessionDependencies(NextProto protocol);

  // Custom proxy service dependency.
  SpdySessionDependencies(NextProto protocol, ProxyService* proxy_service);

  ~SpdySessionDependencies();

  static HttpNetworkSession* SpdyCreateSession(
      SpdySessionDependencies* session_deps);
  static HttpNetworkSession* SpdyCreateSessionDeterministic(
      SpdySessionDependencies* session_deps);
  static HttpNetworkSession::Params CreateSessionParams(
      SpdySessionDependencies* session_deps);

  // NOTE: host_resolver must be ordered before http_auth_handler_factory.
  scoped_ptr<MockHostResolverBase> host_resolver;
  scoped_ptr<CertVerifier> cert_verifier;
  scoped_ptr<TransportSecurityState> transport_security_state;
  scoped_ptr<ProxyService> proxy_service;
  scoped_refptr<SSLConfigService> ssl_config_service;
  scoped_ptr<MockClientSocketFactory> socket_factory;
  scoped_ptr<DeterministicMockClientSocketFactory> deterministic_socket_factory;
  scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
  HttpServerPropertiesImpl http_server_properties;
  bool enable_ip_pooling;
  bool enable_compression;
  bool enable_ping;
  bool enable_user_alternate_protocol_ports;
  NextProto protocol;
  size_t stream_initial_recv_window_size;
  SpdySession::TimeFunc time_func;
  NextProtoVector next_protos;
  std::string trusted_spdy_proxy;
  bool force_spdy_over_ssl;
  bool force_spdy_always;
  bool use_alternate_protocols;
  bool enable_websocket_over_spdy;
  NetLog* net_log;
};

class SpdyURLRequestContext : public URLRequestContext {
 public:
  SpdyURLRequestContext(NextProto protocol,
                        bool force_spdy_over_ssl,
                        bool force_spdy_always);
  ~SpdyURLRequestContext() override;

  MockClientSocketFactory& socket_factory() { return socket_factory_; }

 private:
  MockClientSocketFactory socket_factory_;
  net::URLRequestContextStorage storage_;
};

// Equivalent to pool->GetIfExists(spdy_session_key, BoundNetLog()) != NULL.
bool HasSpdySession(SpdySessionPool* pool, const SpdySessionKey& key);

// Creates a SPDY session for the given key and puts it in the SPDY
// session pool in |http_session|. A SPDY session for |key| must not
// already exist.
base::WeakPtr<SpdySession> CreateInsecureSpdySession(
    const scoped_refptr<HttpNetworkSession>& http_session,
    const SpdySessionKey& key,
    const BoundNetLog& net_log);

// Tries to create a SPDY session for the given key but expects the
// attempt to fail with the given error. A SPDY session for |key| must
// not already exist. The session will be created but close in the
// next event loop iteration.
base::WeakPtr<SpdySession> TryCreateInsecureSpdySessionExpectingFailure(
    const scoped_refptr<HttpNetworkSession>& http_session,
    const SpdySessionKey& key,
    Error expected_error,
    const BoundNetLog& net_log);

// Like CreateInsecureSpdySession(), but uses TLS.
base::WeakPtr<SpdySession> CreateSecureSpdySession(
    const scoped_refptr<HttpNetworkSession>& http_session,
    const SpdySessionKey& key,
    const BoundNetLog& net_log);

// Creates an insecure SPDY session for the given key and puts it in
// |pool|. The returned session will neither receive nor send any
// data. A SPDY session for |key| must not already exist.
base::WeakPtr<SpdySession> CreateFakeSpdySession(SpdySessionPool* pool,
                                                 const SpdySessionKey& key);

// Tries to create an insecure SPDY session for the given key but
// expects the attempt to fail with the given error. The session will
// neither receive nor send any data. A SPDY session for |key| must
// not already exist. The session will be created but close in the
// next event loop iteration.
base::WeakPtr<SpdySession> TryCreateFakeSpdySessionExpectingFailure(
    SpdySessionPool* pool,
    const SpdySessionKey& key,
    Error expected_error);

class SpdySessionPoolPeer {
 public:
  explicit SpdySessionPoolPeer(SpdySessionPool* pool);

  void RemoveAliases(const SpdySessionKey& key);
  void DisableDomainAuthenticationVerification();
  void SetEnableSendingInitialData(bool enabled);

 private:
  SpdySessionPool* const pool_;

  DISALLOW_COPY_AND_ASSIGN(SpdySessionPoolPeer);
};

class SpdyTestUtil {
 public:
  explicit SpdyTestUtil(NextProto protocol);

  // Add the appropriate headers to put |url| into |block|.
  void AddUrlToHeaderBlock(base::StringPiece url,
                           SpdyHeaderBlock* headers) const;

  scoped_ptr<SpdyHeaderBlock> ConstructGetHeaderBlock(
      base::StringPiece url) const;
  scoped_ptr<SpdyHeaderBlock> ConstructGetHeaderBlockForProxy(
      base::StringPiece url) const;
  scoped_ptr<SpdyHeaderBlock> ConstructHeadHeaderBlock(
      base::StringPiece url,
      int64 content_length) const;
  scoped_ptr<SpdyHeaderBlock> ConstructPostHeaderBlock(
      base::StringPiece url,
      int64 content_length) const;
  scoped_ptr<SpdyHeaderBlock> ConstructPutHeaderBlock(
      base::StringPiece url,
      int64 content_length) const;

  // Construct a SPDY frame.  If it is a SYN_STREAM or SYN_REPLY frame (as
  // specified in header_info.kind), the provided headers are included in the
  // frame.
  SpdyFrame* ConstructSpdyFrame(
      const SpdyHeaderInfo& header_info,
      scoped_ptr<SpdyHeaderBlock> headers) const;

  // Construct a SPDY frame.  If it is a SYN_STREAM or SYN_REPLY frame (as
  // specified in header_info.kind), the headers provided in extra_headers and
  // (if non-NULL) tail_headers are concatenated and included in the frame.
  // (extra_headers must always be non-NULL.)
  SpdyFrame* ConstructSpdyFrame(const SpdyHeaderInfo& header_info,
                                const char* const extra_headers[],
                                int extra_header_count,
                                const char* const tail_headers[],
                                int tail_header_count) const;

  // Construct a generic SpdyControlFrame.
  SpdyFrame* ConstructSpdyControlFrame(
      scoped_ptr<SpdyHeaderBlock> headers,
      bool compressed,
      SpdyStreamId stream_id,
      RequestPriority request_priority,
      SpdyFrameType type,
      SpdyControlFlags flags,
      SpdyStreamId associated_stream_id) const;

  // Construct a generic SpdyControlFrame.
  //
  // Warning: extra_header_count is the number of header-value pairs in
  // extra_headers (so half the number of elements), but tail_headers_size is
  // the actual number of elements (both keys and values) in tail_headers.
  // TODO(ttuttle): Fix this inconsistency.
  SpdyFrame* ConstructSpdyControlFrame(
      const char* const extra_headers[],
      int extra_header_count,
      bool compressed,
      SpdyStreamId stream_id,
      RequestPriority request_priority,
      SpdyFrameType type,
      SpdyControlFlags flags,
      const char* const* tail_headers,
      int tail_headers_size,
      SpdyStreamId associated_stream_id) const;

  // Construct an expected SPDY reply string from the given headers.
  std::string ConstructSpdyReplyString(const SpdyHeaderBlock& headers) const;

  // Construct an expected SPDY SETTINGS frame.
  // |settings| are the settings to set.
  // Returns the constructed frame.  The caller takes ownership of the frame.
  SpdyFrame* ConstructSpdySettings(const SettingsMap& settings) const;

  // Constructs an expected SPDY SETTINGS acknowledgement frame, if the protocol
  // version is SPDY4 or higher, or an empty placeholder frame otherwise.
  SpdyFrame* ConstructSpdySettingsAck() const;

  // Construct a SPDY PING frame.
  // Returns the constructed frame.  The caller takes ownership of the frame.
  SpdyFrame* ConstructSpdyPing(uint32 ping_id, bool is_ack) const;

  // Construct a SPDY GOAWAY frame with last_good_stream_id = 0.
  // Returns the constructed frame.  The caller takes ownership of the frame.
  SpdyFrame* ConstructSpdyGoAway() const;

  // Construct a SPDY GOAWAY frame with the specified last_good_stream_id.
  // Returns the constructed frame.  The caller takes ownership of the frame.
  SpdyFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id) const;

  // Construct a SPDY GOAWAY frame with the specified last_good_stream_id,
  // status, and description. Returns the constructed frame. The caller takes
  // ownership of the frame.
  SpdyFrame* ConstructSpdyGoAway(SpdyStreamId last_good_stream_id,
                                 SpdyGoAwayStatus status,
                                 const std::string& desc) const;

  // Construct a SPDY WINDOW_UPDATE frame.
  // Returns the constructed frame.  The caller takes ownership of the frame.
  SpdyFrame* ConstructSpdyWindowUpdate(
      SpdyStreamId stream_id,
      uint32 delta_window_size) const;

  // Construct a SPDY RST_STREAM frame.
  // Returns the constructed frame.  The caller takes ownership of the frame.
  SpdyFrame* ConstructSpdyRstStream(SpdyStreamId stream_id,
                                    SpdyRstStreamStatus status) const;

  // Constructs a standard SPDY GET SYN frame, optionally compressed
  // for |url|.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyGet(const char* const url,
                              bool compressed,
                              SpdyStreamId stream_id,
                              RequestPriority request_priority) const;

  SpdyFrame* ConstructSpdyGetForProxy(const char* const url,
                                      bool compressed,
                                      SpdyStreamId stream_id,
                                      RequestPriority request_priority) const;

  // Constructs a standard SPDY GET SYN frame, optionally compressed.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.  If |direct| is false, the
  // the full url will be used instead of simply the path.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyGet(const char* const extra_headers[],
                              int extra_header_count,
                              bool compressed,
                              int stream_id,
                              RequestPriority request_priority,
                              bool direct) const;

  // Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
  SpdyFrame* ConstructSpdyConnect(const char* const extra_headers[],
                                  int extra_header_count,
                                  int stream_id,
                                  RequestPriority priority) const;

  // Constructs a standard SPDY push SYN frame.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
                               int extra_header_count,
                               int stream_id,
                               int associated_stream_id,
                               const char* url);
  SpdyFrame* ConstructSpdyPush(const char* const extra_headers[],
                               int extra_header_count,
                               int stream_id,
                               int associated_stream_id,
                               const char* url,
                               const char* status,
                               const char* location);

  SpdyFrame* ConstructInitialSpdyPushFrame(scoped_ptr<SpdyHeaderBlock> headers,
                                           int stream_id,
                                           int associated_stream_id);

  SpdyFrame* ConstructSpdyPushHeaders(int stream_id,
                                      const char* const extra_headers[],
                                      int extra_header_count);

  // Construct a SPDY syn (HEADERS or SYN_STREAM, depending on protocol
  // version) carrying exactly the given headers and priority.
  SpdyFrame* ConstructSpdySyn(int stream_id,
                              const SpdyHeaderBlock& headers,
                              RequestPriority priority,
                              bool compressed,
                              bool fin) const;

  // Construct a SPDY reply (HEADERS or SYN_REPLY, depending on protocol
  // version) carrying exactly the given headers, and the default priority
  // (or no priority, depending on protocl version).
  // The |headers| parameter variant is preferred.
  SpdyFrame* ConstructSpdyReply(int stream_id, const SpdyHeaderBlock& headers);

  // Constructs a standard SPDY SYN_REPLY frame to match the SPDY GET.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyGetSynReply(const char* const extra_headers[],
                                      int extra_header_count,
                                      int stream_id);

  // Constructs a standard SPDY SYN_REPLY frame to match the SPDY GET.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyGetSynReplyRedirect(int stream_id);

  // Constructs a standard SPDY SYN_REPLY frame with an Internal Server
  // Error status code.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdySynReplyError(int stream_id);

  // Constructs a standard SPDY SYN_REPLY frame with the specified status code.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdySynReplyError(const char* const status,
                                        const char* const* const extra_headers,
                                        int extra_header_count,
                                        int stream_id);

  // Constructs a standard SPDY POST SYN frame.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyPost(const char* url,
                               SpdyStreamId stream_id,
                               int64 content_length,
                               RequestPriority priority,
                               const char* const extra_headers[],
                               int extra_header_count);

  // Constructs a chunked transfer SPDY POST SYN frame.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructChunkedSpdyPost(const char* const extra_headers[],
                                      int extra_header_count);

  // Constructs a standard SPDY SYN_REPLY frame to match the SPDY POST.
  // |extra_headers| are the extra header-value pairs, which typically
  // will vary the most between calls.
  // Returns a SpdyFrame.
  SpdyFrame* ConstructSpdyPostSynReply(const char* const extra_headers[],
                                       int extra_header_count);

  // Constructs a single SPDY data frame with the contents "hello!"
  SpdyFrame* ConstructSpdyBodyFrame(int stream_id,
                                    bool fin);

  // Constructs a single SPDY data frame with the given content.
  SpdyFrame* ConstructSpdyBodyFrame(int stream_id, const char* data,
                                    uint32 len, bool fin);

  // Wraps |frame| in the payload of a data frame in stream |stream_id|.
  SpdyFrame* ConstructWrappedSpdyFrame(const scoped_ptr<SpdyFrame>& frame,
                                       int stream_id);

  const SpdyHeaderInfo MakeSpdyHeader(SpdyFrameType type);

  // For versions below SPDY4, adds the version HTTP/1.1 header.
  void MaybeAddVersionHeader(SpdyFrameWithNameValueBlockIR* frame_ir) const;
  void MaybeAddVersionHeader(SpdyHeaderBlock* block) const;

  // Maps |priority| to SPDY version priority, and sets it on |frame_ir|.
  void SetPriority(RequestPriority priority, SpdySynStreamIR* frame_ir) const;

  NextProto protocol() const { return protocol_; }
  SpdyMajorVersion spdy_version() const { return spdy_version_; }
  bool is_spdy2() const { return protocol_ < kProtoSPDY3; }
  bool include_version_header() const { return protocol_ < kProtoSPDY4; }
  scoped_ptr<SpdyFramer> CreateFramer(bool compressed) const;

  const char* GetMethodKey() const;
  const char* GetStatusKey() const;
  const char* GetHostKey() const;
  const char* GetSchemeKey() const;
  const char* GetVersionKey() const;
  const char* GetPathKey() const;

 private:
  // |content_length| may be NULL, in which case the content-length
  // header will be omitted.
  scoped_ptr<SpdyHeaderBlock> ConstructHeaderBlock(
      base::StringPiece method,
      base::StringPiece url,
      int64* content_length) const;

  const NextProto protocol_;
  const SpdyMajorVersion spdy_version_;
};

}  // namespace net

#endif  // NET_SPDY_SPDY_TEST_UTIL_COMMON_H_
