// Copyright 2008 Google Inc.
// Author: Lincoln Smith
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <config.h>
#include "headerparser.h"
#include <stdlib.h>  // rand, srand
#include <string>
#include <vector>
#include "testing.h"
#include "varint_bigendian.h"

namespace open_vcdiff {
namespace {  // anonymous

using std::vector;

class VCDiffHeaderParserTest : public testing::Test {
 protected:
#ifndef VCDIFF_HAS_GLOBAL_STRING
  typedef std::string string;
#endif  // !VCDIFF_HAS_GLOBAL_STRING

  static const int kTestSize = 1024;

  VCDiffHeaderParserTest() : parser(NULL) { }

  virtual ~VCDiffHeaderParserTest() {
    delete parser;
  }

  virtual void SetUp() {
    srand(1);  // make sure each test uses the same data set
  }

  void StartParsing() {
    parser = new VCDiffHeaderParser(
        encoded_buffer_.data(),
        encoded_buffer_.data() + encoded_buffer_.size());
    EXPECT_EQ(encoded_buffer_.data(), parser->UnparsedData());
  }

  void VerifyByte(unsigned char expected_value) {
    unsigned char decoded_byte = 0;
    const char* prior_position = parser->UnparsedData();
    EXPECT_TRUE(parser->ParseByte(&decoded_byte));
    EXPECT_EQ(expected_value, decoded_byte);
    EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
    EXPECT_EQ(prior_position + sizeof(unsigned char),
              parser->UnparsedData());
  }

  void VerifyInt32(int32_t expected_value) {
    int32_t decoded_integer = 0;
    const char* prior_position = parser->UnparsedData();
    EXPECT_TRUE(parser->ParseInt32("decoded int32", &decoded_integer));
    EXPECT_EQ(expected_value, decoded_integer);
    EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
    EXPECT_EQ(prior_position + VarintBE<int32_t>::Length(decoded_integer),
              parser->UnparsedData());
  }

  void VerifyUInt32(uint32_t expected_value) {
    uint32_t decoded_integer = 0;
    const char* prior_position = parser->UnparsedData();
    EXPECT_TRUE(parser->ParseUInt32("decoded uint32", &decoded_integer));
    EXPECT_EQ(expected_value, decoded_integer);
    EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
    EXPECT_EQ(prior_position + VarintBE<int64_t>::Length(decoded_integer),
              parser->UnparsedData());
  }

  void VerifyChecksum(VCDChecksum expected_value) {
    VCDChecksum decoded_checksum = 0;
    const char* prior_position = parser->UnparsedData();
    EXPECT_TRUE(parser->ParseChecksum("decoded checksum", &decoded_checksum));
    EXPECT_EQ(expected_value, decoded_checksum);
    EXPECT_EQ(RESULT_SUCCESS, parser->GetResult());
    EXPECT_EQ(prior_position + VarintBE<int64_t>::Length(decoded_checksum),
              parser->UnparsedData());
  }

  string encoded_buffer_;
  VCDiffHeaderParser* parser;
};

TEST_F(VCDiffHeaderParserTest, ParseRandomBytes) {
  vector<unsigned char> byte_values;
  for (int i = 0; i < kTestSize; ++i) {
    unsigned char random_byte = PortableRandomInRange<unsigned char>(0xFF);
    encoded_buffer_.push_back(random_byte);
    byte_values.push_back(random_byte);
  }
  StartParsing();
  for (int position = 0; position < kTestSize; ++position) {
    VerifyByte(byte_values[position]);
  }
  unsigned char decoded_byte = 0;
  EXPECT_FALSE(parser->ParseByte(&decoded_byte));
  EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
            parser->UnparsedData());
}

TEST_F(VCDiffHeaderParserTest, ParseRandomInt32) {
  vector<int32_t> integer_values;
  for (int i = 0; i < kTestSize; ++i) {
    int32_t random_integer = PortableRandomInRange<int32_t>(0x7FFFFFFF);
    VarintBE<int32_t>::AppendToString(random_integer, &encoded_buffer_);
    integer_values.push_back(random_integer);
  }
  StartParsing();
  for (int i = 0; i < kTestSize; ++i) {
    VerifyInt32(integer_values[i]);
  }
  int32_t decoded_integer = 0;
  EXPECT_FALSE(parser->ParseInt32("decoded integer", &decoded_integer));
  EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
            parser->UnparsedData());
}

TEST_F(VCDiffHeaderParserTest, ParseRandomUInt32) {
  vector<uint32_t> integer_values;
  for (int i = 0; i < kTestSize; ++i) {
    uint32_t random_integer = PortableRandomInRange<uint32_t>(0xFFFFFFFF);
    VarintBE<int64_t>::AppendToString(random_integer, &encoded_buffer_);
    integer_values.push_back(random_integer);
  }
  StartParsing();
  uint32_t decoded_integer = 0;
  for (int i = 0; i < kTestSize; ++i) {
    VerifyUInt32(integer_values[i]);
  }
  EXPECT_FALSE(parser->ParseUInt32("decoded integer", &decoded_integer));
  EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
            parser->UnparsedData());
}

TEST_F(VCDiffHeaderParserTest, ParseRandomChecksum) {
  vector<VCDChecksum> checksum_values;
  for (int i = 0; i < kTestSize; ++i) {
    VCDChecksum random_checksum =
        PortableRandomInRange<VCDChecksum>(0xFFFFFFFF);
    VarintBE<int64_t>::AppendToString(random_checksum, &encoded_buffer_);
    checksum_values.push_back(random_checksum);
  }
  StartParsing();
  for (int i = 0; i < kTestSize; ++i) {
    VerifyChecksum(checksum_values[i]);
  }
  VCDChecksum decoded_checksum = 0;
  EXPECT_FALSE(parser->ParseChecksum("decoded checksum", &decoded_checksum));
  EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size(),
            parser->UnparsedData());
}

TEST_F(VCDiffHeaderParserTest, ParseMixed) {
  VarintBE<int64_t>::AppendToString(0xCAFECAFE, &encoded_buffer_);
  encoded_buffer_.push_back(0xFF);
  VarintBE<int32_t>::AppendToString(0x02020202, &encoded_buffer_);
  VarintBE<int64_t>::AppendToString(0xCAFECAFE, &encoded_buffer_);
  encoded_buffer_.push_back(0xFF);
  encoded_buffer_.push_back(0xFF);
  StartParsing();
  VerifyUInt32(0xCAFECAFE);
  VerifyByte(0xFF);
  VerifyInt32(0x02020202);
  VerifyChecksum(0xCAFECAFE);
  int32_t incomplete_int32 = 0;
  EXPECT_FALSE(parser->ParseInt32("incomplete Varint", &incomplete_int32));
  EXPECT_EQ(0, incomplete_int32);
  EXPECT_EQ(RESULT_END_OF_DATA, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data() + encoded_buffer_.size() - 2,
            parser->UnparsedData());
}

TEST_F(VCDiffHeaderParserTest, ParseInvalidVarint) {
  // Start with a byte that has the continuation bit plus a high-order bit set
  encoded_buffer_.append(1, static_cast<char>(0xC0));
  // Add too many bytes with continuation bits
  encoded_buffer_.append(6, static_cast<char>(0x80));
  StartParsing();
  int32_t invalid_int32 = 0;
  EXPECT_FALSE(parser->ParseInt32("invalid Varint", &invalid_int32));
  EXPECT_EQ(0, invalid_int32);
  EXPECT_EQ(RESULT_ERROR, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data(), parser->UnparsedData());
  // After the parse failure, any other call to Parse... should return an error,
  // even though there is still a byte that could be read as valid.
  unsigned char decoded_byte = 0;
  EXPECT_FALSE(parser->ParseByte(&decoded_byte));
  EXPECT_EQ(0, decoded_byte);
  EXPECT_EQ(RESULT_ERROR, parser->GetResult());
  EXPECT_EQ(encoded_buffer_.data(), parser->UnparsedData());
}

}  //  namespace open_vcdiff
}  //  anonymous namespace
