// Copyright 2018 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 "quiche/http2/hpack/varint/hpack_varint_decoder.h"

// Test HpackVarintDecoder against hardcoded data.

#include <stddef.h>

#include <utility>

#include "absl/base/macros.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "quiche/http2/test_tools/random_decoder_test_base.h"
#include "quiche/http2/test_tools/verify_macros.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/common/platform/api/quiche_test.h"

using ::testing::AssertionSuccess;

namespace http2 {
namespace test {
namespace {

class HpackVarintDecoderTest
    : public RandomDecoderTest,
      public ::testing::WithParamInterface<std::tuple<uint8_t, const char*>> {
 protected:
  HpackVarintDecoderTest()
      : high_bits_(std::get<0>(GetParam())),
        suffix_(absl::HexStringToBytes(std::get<1>(GetParam()))),
        prefix_length_(0) {}

  void DecodeExpectSuccess(absl::string_view data, uint32_t prefix_length,
                           uint64_t expected_value) {
    Validator validator = [expected_value, this](
                              const DecodeBuffer& /*db*/,
                              DecodeStatus /*status*/) -> AssertionResult {
      HTTP2_VERIFY_EQ(expected_value, decoder_.value())
          << "Value doesn't match expected: " << decoder_.value()
          << " != " << expected_value;
      return AssertionSuccess();
    };

    // First validate that decoding is done and that we've advanced the cursor
    // the expected amount.
    validator =
        ValidateDoneAndOffset(/* offset = */ data.size(), std::move(validator));

    EXPECT_TRUE(Decode(data, prefix_length, std::move(validator)));

    EXPECT_EQ(expected_value, decoder_.value());
  }

  void DecodeExpectError(absl::string_view data, uint32_t prefix_length) {
    Validator validator = [](const DecodeBuffer& /*db*/,
                             DecodeStatus status) -> AssertionResult {
      HTTP2_VERIFY_EQ(DecodeStatus::kDecodeError, status);
      return AssertionSuccess();
    };

    EXPECT_TRUE(Decode(data, prefix_length, std::move(validator)));
  }

 private:
  AssertionResult Decode(absl::string_view data, uint32_t prefix_length,
                         const Validator validator) {
    prefix_length_ = prefix_length;

    // Copy |data| so that it can be modified.
    std::string data_copy(data);

    // Bits of the first byte not part of the prefix should be ignored.
    uint8_t high_bits_mask = 0b11111111 << prefix_length_;
    data_copy[0] |= (high_bits_mask & high_bits_);

    // Extra bytes appended to the input should be ignored.
    data_copy.append(suffix_);

    DecodeBuffer b(data_copy);

    // StartDecoding, above, requires the DecodeBuffer be non-empty so that it
    // can call Start with the prefix byte.
    bool return_non_zero_on_first = true;

    return DecodeAndValidateSeveralWays(&b, return_non_zero_on_first,
                                        validator);
  }

  DecodeStatus StartDecoding(DecodeBuffer* b) override {
    QUICHE_CHECK_LT(0u, b->Remaining());
    uint8_t prefix = b->DecodeUInt8();
    return decoder_.Start(prefix, prefix_length_, b);
  }

  DecodeStatus ResumeDecoding(DecodeBuffer* b) override {
    return decoder_.Resume(b);
  }

  // Bits of the first byte not part of the prefix.
  const uint8_t high_bits_;
  // Extra bytes appended to the input.
  const std::string suffix_;

  HpackVarintDecoder decoder_;
  uint8_t prefix_length_;
};

INSTANTIATE_TEST_SUITE_P(
    HpackVarintDecoderTest, HpackVarintDecoderTest,
    ::testing::Combine(
        // Bits of the first byte not part of the prefix should be ignored.
        ::testing::Values(0b00000000, 0b11111111, 0b10101010),
        // Extra bytes appended to the input should be ignored.
        ::testing::Values("", "00", "666f6f")));

struct {
  const char* data;
  uint32_t prefix_length;
  uint64_t expected_value;
} kSuccessTestData[] = {
    // Zero value with different prefix lengths.
    {"00", 3, 0},
    {"00", 4, 0},
    {"00", 5, 0},
    {"00", 6, 0},
    {"00", 7, 0},
    {"00", 8, 0},
    // Small values that fit in the prefix.
    {"06", 3, 6},
    {"0d", 4, 13},
    {"10", 5, 16},
    {"29", 6, 41},
    {"56", 7, 86},
    {"bf", 8, 191},
    // Values of 2^n-1, which have an all-zero extension byte.
    {"0700", 3, 7},
    {"0f00", 4, 15},
    {"1f00", 5, 31},
    {"3f00", 6, 63},
    {"7f00", 7, 127},
    {"ff00", 8, 255},
    // Values of 2^n-1, plus one extra byte of padding.
    {"078000", 3, 7},
    {"0f8000", 4, 15},
    {"1f8000", 5, 31},
    {"3f8000", 6, 63},
    {"7f8000", 7, 127},
    {"ff8000", 8, 255},
    // Values requiring one extension byte.
    {"0760", 3, 103},
    {"0f2a", 4, 57},
    {"1f7f", 5, 158},
    {"3f02", 6, 65},
    {"7f49", 7, 200},
    {"ff6f", 8, 366},
    // Values requiring one extension byte, plus one byte of padding.
    {"07e000", 3, 103},
    {"0faa00", 4, 57},
    {"1fff00", 5, 158},
    {"3f8200", 6, 65},
    {"7fc900", 7, 200},
    {"ffef00", 8, 366},
    // Values requiring one extension byte, plus two bytes of padding.
    {"07e08000", 3, 103},
    {"0faa8000", 4, 57},
    {"1fff8000", 5, 158},
    {"3f828000", 6, 65},
    {"7fc98000", 7, 200},
    {"ffef8000", 8, 366},
    // Values requiring one extension byte, plus the maximum amount of padding.
    {"07e0808080808080808000", 3, 103},
    {"0faa808080808080808000", 4, 57},
    {"1fff808080808080808000", 5, 158},
    {"3f82808080808080808000", 6, 65},
    {"7fc9808080808080808000", 7, 200},
    {"ffef808080808080808000", 8, 366},
    // Values requiring two extension bytes.
    {"07b260", 3, 12345},
    {"0f8a2a", 4, 5401},
    {"1fa87f", 5, 16327},
    {"3fd002", 6, 399},
    {"7fff49", 7, 9598},
    {"ffe32f", 8, 6370},
    // Values requiring two extension bytes, plus one byte of padding.
    {"07b2e000", 3, 12345},
    {"0f8aaa00", 4, 5401},
    {"1fa8ff00", 5, 16327},
    {"3fd08200", 6, 399},
    {"7fffc900", 7, 9598},
    {"ffe3af00", 8, 6370},
    // Values requiring two extension bytes, plus the maximum amount of padding.
    {"07b2e080808080808000", 3, 12345},
    {"0f8aaa80808080808000", 4, 5401},
    {"1fa8ff80808080808000", 5, 16327},
    {"3fd08280808080808000", 6, 399},
    {"7fffc980808080808000", 7, 9598},
    {"ffe3af80808080808000", 8, 6370},
    // Values requiring three extension bytes.
    {"078ab260", 3, 1579281},
    {"0fc18a2a", 4, 689488},
    {"1fada87f", 5, 2085964},
    {"3fa0d002", 6, 43103},
    {"7ffeff49", 7, 1212541},
    {"ff93de23", 8, 585746},
    // Values requiring three extension bytes, plus one byte of padding.
    {"078ab2e000", 3, 1579281},
    {"0fc18aaa00", 4, 689488},
    {"1fada8ff00", 5, 2085964},
    {"3fa0d08200", 6, 43103},
    {"7ffeffc900", 7, 1212541},
    {"ff93dea300", 8, 585746},
    // Values requiring four extension bytes.
    {"079f8ab260", 3, 202147110},
    {"0fa2c18a2a", 4, 88252593},
    {"1fd0ada87f", 5, 266999535},
    {"3ff9a0d002", 6, 5509304},
    {"7f9efeff49", 7, 155189149},
    {"ffaa82f404", 8, 10289705},
    // Values requiring four extension bytes, plus one byte of padding.
    {"079f8ab2e000", 3, 202147110},
    {"0fa2c18aaa00", 4, 88252593},
    {"1fd0ada8ff00", 5, 266999535},
    {"3ff9a0d08200", 6, 5509304},
    {"7f9efeffc900", 7, 155189149},
    {"ffaa82f48400", 8, 10289705},
    // Values requiring six extension bytes.
    {"0783aa9f8ab260", 3, 3311978140938},
    {"0ff0b0a2c18a2a", 4, 1445930244223},
    {"1fda84d0ada87f", 5, 4374519874169},
    {"3fb5fbf9a0d002", 6, 90263420404},
    {"7fcff19efeff49", 7, 2542616951118},
    {"ff9fa486bbc327", 8, 1358138807070},
    // Values requiring eight extension bytes.
    {"07f19883aa9f8ab260", 3, 54263449861016696},
    {"0f84fdf0b0a2c18a2a", 4, 23690121121119891},
    {"1fa0dfda84d0ada87f", 5, 71672133617889215},
    {"3f9ff0b5fbf9a0d002", 6, 1478875878881374},
    {"7ffbc1cff19efeff49", 7, 41658236125045114},
    {"ff91b6fb85af99c342", 8, 37450237664484368},
    // Values requiring ten extension bytes.
    {"0794f1f19883aa9f8ab201", 3, 12832019021693745307u},
    {"0fa08f84fdf0b0a2c18a01", 4, 9980690937382242223u},
    {"1fbfdda0dfda84d0ada801", 5, 12131360551794650846u},
    {"3f9dc79ff0b5fbf9a0d001", 6, 15006530362736632796u},
    {"7f8790fbc1cff19efeff01", 7, 18445754019193211014u},
    {"fffba8c5b8d3fe9f8c8401", 8, 9518498503615141242u},
    // Maximum value: 2^64-1.
    {"07f8ffffffffffffffff01", 3, 18446744073709551615u},
    {"0ff0ffffffffffffffff01", 4, 18446744073709551615u},
    {"1fe0ffffffffffffffff01", 5, 18446744073709551615u},
    {"3fc0ffffffffffffffff01", 6, 18446744073709551615u},
    {"7f80ffffffffffffffff01", 7, 18446744073709551615u},
    {"ff80feffffffffffffff01", 8, 18446744073709551615u},
    // Examples from RFC7541 C.1.
    {"0a", 5, 10},
    {"1f9a0a", 5, 1337},
};

TEST_P(HpackVarintDecoderTest, Success) {
  for (size_t i = 0; i < ABSL_ARRAYSIZE(kSuccessTestData); ++i) {
    DecodeExpectSuccess(absl::HexStringToBytes(kSuccessTestData[i].data),
                        kSuccessTestData[i].prefix_length,
                        kSuccessTestData[i].expected_value);
  }
}

struct {
  const char* data;
  uint32_t prefix_length;
} kErrorTestData[] = {
    // Too many extension bytes, all 0s (except for extension bit in each byte).
    {"0780808080808080808080", 3},
    {"0f80808080808080808080", 4},
    {"1f80808080808080808080", 5},
    {"3f80808080808080808080", 6},
    {"7f80808080808080808080", 7},
    {"ff80808080808080808080", 8},
    // Too many extension bytes, all 1s.
    {"07ffffffffffffffffffff", 3},
    {"0fffffffffffffffffffff", 4},
    {"1fffffffffffffffffffff", 5},
    {"3fffffffffffffffffffff", 6},
    {"7fffffffffffffffffffff", 7},
    {"ffffffffffffffffffffff", 8},
    // Value of 2^64, one higher than maximum of 2^64-1.
    {"07f9ffffffffffffffff01", 3},
    {"0ff1ffffffffffffffff01", 4},
    {"1fe1ffffffffffffffff01", 5},
    {"3fc1ffffffffffffffff01", 6},
    {"7f81ffffffffffffffff01", 7},
    {"ff81feffffffffffffff01", 8},
    // Maximum value: 2^64-1, with one byte of padding.
    {"07f8ffffffffffffffff8100", 3},
    {"0ff0ffffffffffffffff8100", 4},
    {"1fe0ffffffffffffffff8100", 5},
    {"3fc0ffffffffffffffff8100", 6},
    {"7f80ffffffffffffffff8100", 7},
    {"ff80feffffffffffffff8100", 8}};

TEST_P(HpackVarintDecoderTest, Error) {
  for (size_t i = 0; i < ABSL_ARRAYSIZE(kErrorTestData); ++i) {
    DecodeExpectError(absl::HexStringToBytes(kErrorTestData[i].data),
                      kErrorTestData[i].prefix_length);
  }
}

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