// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 <cstdint>
#include <cstdlib>
#include <cstring>
#include <string>
#ifdef NDEBUG
#include <vector>
#endif

#include "kudu/util/group_varint-inl.h"

#include <boost/preprocessor/arithmetic/dec.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/control/iif.hpp>
#include <boost/preprocessor/control/while.hpp>
#include <boost/preprocessor/list/fold_left.hpp>
#include <boost/preprocessor/logical/bitand.hpp>
#include <boost/preprocessor/logical/bool.hpp>
#include <boost/preprocessor/logical/compl.hpp>
#include <boost/preprocessor/seq/elem.hpp>
#include <boost/preprocessor/seq/fold_left.hpp>
#include <boost/preprocessor/seq/size.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/variadic/elem.hpp>
#include <boost/tti/has_template.hpp>
#include <boost/utility/binary.hpp>
#include <gtest/gtest.h>

#include "kudu/util/faststring.h"
#ifdef NDEBUG
#include "kudu/util/stopwatch.h"
#endif

namespace kudu {
namespace coding {

extern void DumpSSETable();

// Encodes the given four ints as group-varint, then
// decodes and ensures the result is the same.
static void DoTestRoundTripGVI32(
  uint32_t a, uint32_t b, uint32_t c, uint32_t d,
  bool use_sse = false) {
  faststring buf;
  AppendGroupVarInt32(&buf, a, b, c, d);

  int real_size = buf.size();

  // The implementations actually read past the group varint,
  // so append some extra padding data to ensure that it's not reading
  // uninitialized memory. The SSE implementation uses 128-bit reads
  // and the non-SSE one uses 32-bit reads.
  buf.append(std::string(use_sse ? 16 : 4, 'x'));

  uint32_t ret[4];

  const uint8_t *end;

#ifndef __aarch64__
  if (use_sse) {
    end = DecodeGroupVarInt32_SSE(
      buf.data(), &ret[0], &ret[1], &ret[2], &ret[3]);
  } else {
    end = DecodeGroupVarInt32(
      buf.data(), &ret[0], &ret[1], &ret[2], &ret[3]);
  }
#else
  end = DecodeGroupVarInt32(buf.data(), &ret[0], &ret[1], &ret[2], &ret[3]);
#endif //__aarch64__

  ASSERT_EQ(a, ret[0]);
  ASSERT_EQ(b, ret[1]);
  ASSERT_EQ(c, ret[2]);
  ASSERT_EQ(d, ret[3]);
  ASSERT_EQ(end, buf.data() + real_size);
}


TEST(TestGroupVarInt, TestSSETable) {
  DumpSSETable();
  faststring buf;
  AppendGroupVarInt32(&buf, 0, 0, 0, 0);
  DoTestRoundTripGVI32(0, 0, 0, 0, true);
  DoTestRoundTripGVI32(1, 2, 3, 4, true);
  DoTestRoundTripGVI32(1, 2000, 3, 200000, true);
}

TEST(TestGroupVarInt, TestGroupVarInt) {
  faststring buf;
  AppendGroupVarInt32(&buf, 0, 0, 0, 0);
  ASSERT_EQ(5UL, buf.size());
  ASSERT_EQ(0, memcmp("\x00\x00\x00\x00\x00", buf.data(), 5));
  buf.clear();

  // All 1-byte
  AppendGroupVarInt32(&buf, 1, 2, 3, 254);
  ASSERT_EQ(5UL, buf.size());
  ASSERT_EQ(0, memcmp("\x00\x01\x02\x03\xfe", buf.data(), 5));
  buf.clear();

  // Mixed 1-byte and 2-byte
  AppendGroupVarInt32(&buf, 256, 2, 3, 65535);
  ASSERT_EQ(7UL, buf.size());
  ASSERT_EQ(BOOST_BINARY(01 00 00 01), buf.at(0));
  ASSERT_EQ(256, *reinterpret_cast<const uint16_t *>(&buf[1]));
  ASSERT_EQ(2, *reinterpret_cast<const uint8_t *>(&buf[3]));
  ASSERT_EQ(3, *reinterpret_cast<const uint8_t *>(&buf[4]));
  ASSERT_EQ(65535, *reinterpret_cast<const uint16_t *>(&buf[5]));
}


// Round-trip encode/decodes using group varint
TEST(TestGroupVarInt, TestRoundTrip) {
  // A few simple tests.
  DoTestRoundTripGVI32(0, 0, 0, 0);
  DoTestRoundTripGVI32(1, 2, 3, 4);
  DoTestRoundTripGVI32(1, 2000, 3, 200000);

  // Then a randomized test.
  for (int i = 0; i < 10000; i++) {
    DoTestRoundTripGVI32(random(), random(), random(), random());
  }
}

#ifdef NDEBUG
TEST(TestGroupVarInt, EncodingBenchmark) {
  int n_ints = 1000000;

  std::vector<uint32_t> ints;
  ints.reserve(n_ints);
  for (int i = 0; i < n_ints; i++) {
    ints.push_back(i);
  }

  faststring s;
  // conservative reservation
  s.reserve(ints.size() * 4);

  LOG_TIMING(INFO, "Benchmark") {
    for (int i = 0; i < 100; i++) {
      s.clear();
      AppendGroupVarInt32Sequence(&s, 0, &ints[0], n_ints);
    }
  }
}
#endif
} // namespace coding
} // namespace kudu
