// 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 <map>
#include <vector>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/quic/crypto/crypto_framer.h"
#include "net/quic/crypto/crypto_protocol.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/test/disabled_if_big_endian.h"

using base::StringPiece;
using std::map;
using std::string;
using std::vector;

namespace net {

namespace {

char* AsChars(unsigned char* data) {
  return reinterpret_cast<char*>(data);
}

}  // namespace

namespace test {

class TestCryptoVisitor : public ::net::CryptoFramerVisitorInterface {
 public:
  TestCryptoVisitor()
      : error_count_(0) {
  }

  ~TestCryptoVisitor() {}

  virtual void OnError(CryptoFramer* framer) {
    LOG(ERROR) << "CryptoFramer Error: " << framer->error();
    error_count_++;
  }

  virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) {
    message_tags_.push_back(message.tag);
    message_maps_.push_back(map<CryptoTag, string>());
    CryptoTagValueMap::const_iterator it = message.tag_value_map.begin();
    while (it != message.tag_value_map.end()) {
      message_maps_.back()[it->first] = it->second.as_string();
      ++it;
    }
  }

  CryptoFramer framer_;

  // Counters from the visitor callbacks.
  int error_count_;

  CryptoTagVector message_tags_;
  vector<map<CryptoTag, string> > message_maps_;
};

}  // namespace test

TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ConstructHandshakeMessage)) {
  CryptoHandshakeMessage message;
  message.tag = 0xFFAA7733;
  message.tag_value_map[0x12345678] = "abcdef";
  message.tag_value_map[0x12345679] = "ghijk";
  message.tag_value_map[0x1234567A] = "lmnopqr";

  unsigned char packet[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0x03, 0x00,
    // tag 1
    0x78, 0x56, 0x34, 0x12,
    // tag 2
    0x79, 0x56, 0x34, 0x12,
    // tag 3
    0x7A, 0x56, 0x34, 0x12,
    // len 1
    0x06, 0x00,
    // len 2
    0x05, 0x00,
    // len 3
    0x07, 0x00,
    // padding
    0xAB, 0xAB,
    // value 1
    'a',  'b',  'c',  'd',
    'e',  'f',
    // value 2
    'g',  'h',  'i',  'j',
    'k',
    // value 3
    'l',  'm',  'n',  'o',
    'p',  'q',  'r',
  };

  CryptoFramer framer;
  scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
  ASSERT_TRUE(data.get() != NULL);
  test::CompareCharArraysWithHexError("constructed packet",
                                      data->data(), data->length(),
                                      AsChars(packet), arraysize(packet));
}

TEST(CryptoFramerTest,
     DISABLED_IF_BIG_ENDIAN(ConstructHandshakeMessageWithTwoKeys)) {
  CryptoHandshakeMessage message;
  message.tag = 0xFFAA7733;
  message.tag_value_map[0x12345678] = "abcdef";
  message.tag_value_map[0x12345679] = "ghijk";

  unsigned char packet[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0x02, 0x00,
    // tag 1
    0x78, 0x56, 0x34, 0x12,
    // tag 2
    0x79, 0x56, 0x34, 0x12,
    // len 1
    0x06, 0x00,
    // len 2
    0x05, 0x00,
    // value 1
    'a',  'b',  'c',  'd',
    'e',  'f',
    // value 2
    'g',  'h',  'i',  'j',
    'k',
  };

  CryptoFramer framer;
  scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
  ASSERT_TRUE(data.get() != NULL);

  test::CompareCharArraysWithHexError("constructed packet",
                                      data->data(), data->length(),
                                      AsChars(packet), arraysize(packet));
}

TEST(CryptoFramerTest, ConstructHandshakeMessageTooManyEntries) {
  CryptoHandshakeMessage message;
  message.tag = 0xFFAA7733;
  for (uint32 key = 1; key <= kMaxEntries + 1; ++key) {
    message.tag_value_map[key] = "abcdef";
  }

  CryptoFramer framer;
  scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
  EXPECT_TRUE(data.get() == NULL);
}


TEST(CryptoFramerTest, ConstructHandshakeMessageInvalidLength) {
  CryptoHandshakeMessage message;
  message.tag = 0xFFAA7733;
  message.tag_value_map[0x12345678] = "";

  CryptoFramer framer;
  scoped_ptr<QuicData> data(framer.ConstructHandshakeMessage(message));
  EXPECT_TRUE(data.get() == NULL);
}

TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInput)) {
  test::TestCryptoVisitor visitor;
  CryptoFramer framer;
  framer.set_visitor(&visitor);

  unsigned char input[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0x02, 0x00,
    // tag 1
    0x78, 0x56, 0x34, 0x12,
    // tag 2
    0x79, 0x56, 0x34, 0x12,
    // len 1
    0x06, 0x00,
    // len 2
    0x05, 0x00,
    // value 1
    'a',  'b',  'c',  'd',
    'e',  'f',
    // value 2
    'g',  'h',  'i',  'j',
    'k',
  };

  EXPECT_TRUE(framer.ProcessInput(StringPiece(AsChars(input),
                                              arraysize(input))));
  ASSERT_EQ(1u, visitor.message_tags_.size());
  EXPECT_EQ(0xFFAA7733, visitor.message_tags_[0]);
  EXPECT_EQ(2u, visitor.message_maps_[0].size());
  EXPECT_EQ("abcdef",visitor.message_maps_[0][0x12345678]);
  EXPECT_EQ("ghijk", visitor.message_maps_[0][0x12345679]);
}

TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInputIncrementally)) {
  test::TestCryptoVisitor visitor;
  CryptoFramer framer;
  framer.set_visitor(&visitor);

  unsigned char input[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0x02, 0x00,
    // tag 1
    0x78, 0x56, 0x34, 0x12,
    // tag 2
    0x79, 0x56, 0x34, 0x12,
    // len 1
    0x06, 0x00,
    // len 2
    0x05, 0x00,
    // value 1
    'a',  'b',  'c',  'd',
    'e',  'f',
    // value 2
    'g',  'h',  'i',  'j',
    'k',
  };

  for (size_t i = 0; i < arraysize(input); i++) {
    EXPECT_TRUE(framer.ProcessInput(StringPiece(AsChars(input)+ i, 1)));
  }
  ASSERT_EQ(1u, visitor.message_tags_.size());
  EXPECT_EQ(0xFFAA7733, visitor.message_tags_[0]);
  EXPECT_EQ(2u, visitor.message_maps_[0].size());
  EXPECT_EQ("abcdef",visitor.message_maps_[0][0x12345678]);
  EXPECT_EQ("ghijk", visitor.message_maps_[0][0x12345679]);
}

TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInputTagsOutOfOrder)) {
  test::TestCryptoVisitor visitor;
  CryptoFramer framer;
  framer.set_visitor(&visitor);

  unsigned char input[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0x02, 0x00,
    // tag 1
    0x79, 0x56, 0x34, 0x12,
    // tag 2
    0x78, 0x56, 0x34, 0x12,
  };

  EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
                                               arraysize(input))));
  EXPECT_EQ(QUIC_CRYPTO_TAGS_OUT_OF_ORDER, framer.error());
}

TEST(CryptoFramerTest, ProcessInputTooManyEntries) {
  test::TestCryptoVisitor visitor;
  CryptoFramer framer;
  framer.set_visitor(&visitor);

  unsigned char input[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0xA0, 0x00,
  };

  EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
                                               arraysize(input))));
  EXPECT_EQ(QUIC_CRYPTO_TOO_MANY_ENTRIES, framer.error());
}

TEST(CryptoFramerTest, DISABLED_IF_BIG_ENDIAN(ProcessInputInvalidLength)) {
  test::TestCryptoVisitor visitor;
  CryptoFramer framer;
  framer.set_visitor(&visitor);

  unsigned char input[] = {
    // tag
    0x33, 0x77, 0xAA, 0xFF,
    // num entries
    0x02, 0x00,
    // tag 1
    0x78, 0x56, 0x34, 0x12,
    // tag 2
    0x79, 0x56, 0x34, 0x12,
    // len 1
    0x00, 0x00,
    // len 2
    0x05, 0x00,
  };

  EXPECT_FALSE(framer.ProcessInput(StringPiece(AsChars(input),
                                               arraysize(input))));
  EXPECT_EQ(QUIC_CRYPTO_INVALID_VALUE_LENGTH, framer.error());
}

}  // namespace net
