// Copyright 2017 The Abseil Authors.
//
// 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 "absl/base/internal/endian.h"

#include <algorithm>
#include <cstdint>
#include <limits>
#include <random>
#include <vector>

#include "gtest/gtest.h"
#include "absl/base/config.h"

namespace absl {
namespace {

const uint64_t kInitialNumber{0x0123456789abcdef};
const uint64_t k64Value{kInitialNumber};
const uint32_t k32Value{0x01234567};
const uint16_t k16Value{0x0123};
const int kNumValuesToTest = 1000000;
const int kRandomSeed = 12345;

#if defined(ABSL_IS_BIG_ENDIAN)
const uint64_t kInitialInNetworkOrder{kInitialNumber};
const uint64_t k64ValueLE{0xefcdab8967452301};
const uint32_t k32ValueLE{0x67452301};
const uint16_t k16ValueLE{0x2301};

const uint64_t k64ValueBE{kInitialNumber};
const uint32_t k32ValueBE{k32Value};
const uint16_t k16ValueBE{k16Value};
#elif defined(ABSL_IS_LITTLE_ENDIAN)
const uint64_t kInitialInNetworkOrder{0xefcdab8967452301};
const uint64_t k64ValueLE{kInitialNumber};
const uint32_t k32ValueLE{k32Value};
const uint16_t k16ValueLE{k16Value};

const uint64_t k64ValueBE{0xefcdab8967452301};
const uint32_t k32ValueBE{0x67452301};
const uint16_t k16ValueBE{0x2301};
#endif

template<typename T>
std::vector<T> GenerateAllValuesForType() {
  std::vector<T> result;
  T next = std::numeric_limits<T>::min();
  while (true) {
    result.push_back(next);
    if (next == std::numeric_limits<T>::max()) {
      return result;
    }
    ++next;
  }
}

template<typename T>
std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) {
  std::vector<T> result;
  std::mt19937_64 rng(kRandomSeed);
  for (size_t i = 0; i < numValuesToTest; ++i) {
    result.push_back(rng());
  }
  return result;
}

void ManualByteSwap(char* bytes, int length) {
  if (length == 1)
    return;

  EXPECT_EQ(0, length % 2);
  for (int i = 0; i < length / 2; ++i) {
    int j = (length - 1) - i;
    using std::swap;
    swap(bytes[i], bytes[j]);
  }
}

template<typename T>
inline T UnalignedLoad(const char* p) {
  static_assert(
      sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
      "Unexpected type size");

  switch (sizeof(T)) {
    case 1: return *reinterpret_cast<const T*>(p);
    case 2:
      return ABSL_INTERNAL_UNALIGNED_LOAD16(p);
    case 4:
      return ABSL_INTERNAL_UNALIGNED_LOAD32(p);
    case 8:
      return ABSL_INTERNAL_UNALIGNED_LOAD64(p);
    default:
      // Suppresses invalid "not all control paths return a value" on MSVC
      return {};
  }
}

template <typename T, typename ByteSwapper>
static void GBSwapHelper(const std::vector<T>& host_values_to_test,
                         const ByteSwapper& byte_swapper) {
  // Test byte_swapper against a manual byte swap.
  for (typename std::vector<T>::const_iterator it = host_values_to_test.begin();
       it != host_values_to_test.end(); ++it) {
    T host_value = *it;

    char actual_value[sizeof(host_value)];
    memcpy(actual_value, &host_value, sizeof(host_value));
    byte_swapper(actual_value);

    char expected_value[sizeof(host_value)];
    memcpy(expected_value, &host_value, sizeof(host_value));
    ManualByteSwap(expected_value, sizeof(host_value));

    ASSERT_EQ(0, memcmp(actual_value, expected_value, sizeof(host_value)))
        << "Swap output for 0x" << std::hex << host_value << " does not match. "
        << "Expected: 0x" << UnalignedLoad<T>(expected_value) << "; "
        << "actual: 0x" <<  UnalignedLoad<T>(actual_value);
  }
}

void Swap16(char* bytes) {
  ABSL_INTERNAL_UNALIGNED_STORE16(
      bytes, gbswap_16(ABSL_INTERNAL_UNALIGNED_LOAD16(bytes)));
}

void Swap32(char* bytes) {
  ABSL_INTERNAL_UNALIGNED_STORE32(
      bytes, gbswap_32(ABSL_INTERNAL_UNALIGNED_LOAD32(bytes)));
}

void Swap64(char* bytes) {
  ABSL_INTERNAL_UNALIGNED_STORE64(
      bytes, gbswap_64(ABSL_INTERNAL_UNALIGNED_LOAD64(bytes)));
}

TEST(EndianessTest, Uint16) {
  GBSwapHelper(GenerateAllValuesForType<uint16_t>(), &Swap16);
}

TEST(EndianessTest, Uint32) {
  GBSwapHelper(GenerateRandomIntegers<uint32_t>(kNumValuesToTest), &Swap32);
}

TEST(EndianessTest, Uint64) {
  GBSwapHelper(GenerateRandomIntegers<uint64_t>(kNumValuesToTest), &Swap64);
}

TEST(EndianessTest, ghtonll_gntohll) {
  // Test that absl::ghtonl compiles correctly
  uint32_t test = 0x01234567;
  EXPECT_EQ(absl::gntohl(absl::ghtonl(test)), test);

  uint64_t comp = absl::ghtonll(kInitialNumber);
  EXPECT_EQ(comp, kInitialInNetworkOrder);
  comp = absl::gntohll(kInitialInNetworkOrder);
  EXPECT_EQ(comp, kInitialNumber);

  // Test that htonll and ntohll are each others' inverse functions on a
  // somewhat assorted batch of numbers. 37 is chosen to not be anything
  // particularly nice base 2.
  uint64_t value = 1;
  for (int i = 0; i < 100; ++i) {
    comp = absl::ghtonll(absl::gntohll(value));
    EXPECT_EQ(value, comp);
    comp = absl::gntohll(absl::ghtonll(value));
    EXPECT_EQ(value, comp);
    value *= 37;
  }
}

TEST(EndianessTest, little_endian) {
  // Check little_endian uint16_t.
  uint64_t comp = little_endian::FromHost16(k16Value);
  EXPECT_EQ(comp, k16ValueLE);
  comp = little_endian::ToHost16(k16ValueLE);
  EXPECT_EQ(comp, k16Value);

  // Check little_endian uint32_t.
  comp = little_endian::FromHost32(k32Value);
  EXPECT_EQ(comp, k32ValueLE);
  comp = little_endian::ToHost32(k32ValueLE);
  EXPECT_EQ(comp, k32Value);

  // Check little_endian uint64_t.
  comp = little_endian::FromHost64(k64Value);
  EXPECT_EQ(comp, k64ValueLE);
  comp = little_endian::ToHost64(k64ValueLE);
  EXPECT_EQ(comp, k64Value);

  // Check little-endian Load and store functions.
  uint16_t u16Buf;
  uint32_t u32Buf;
  uint64_t u64Buf;

  little_endian::Store16(&u16Buf, k16Value);
  EXPECT_EQ(u16Buf, k16ValueLE);
  comp = little_endian::Load16(&u16Buf);
  EXPECT_EQ(comp, k16Value);

  little_endian::Store32(&u32Buf, k32Value);
  EXPECT_EQ(u32Buf, k32ValueLE);
  comp = little_endian::Load32(&u32Buf);
  EXPECT_EQ(comp, k32Value);

  little_endian::Store64(&u64Buf, k64Value);
  EXPECT_EQ(u64Buf, k64ValueLE);
  comp = little_endian::Load64(&u64Buf);
  EXPECT_EQ(comp, k64Value);
}

TEST(EndianessTest, big_endian) {
  // Check big-endian Load and store functions.
  uint16_t u16Buf;
  uint32_t u32Buf;
  uint64_t u64Buf;

  unsigned char buffer[10];
  big_endian::Store16(&u16Buf, k16Value);
  EXPECT_EQ(u16Buf, k16ValueBE);
  uint64_t comp = big_endian::Load16(&u16Buf);
  EXPECT_EQ(comp, k16Value);

  big_endian::Store32(&u32Buf, k32Value);
  EXPECT_EQ(u32Buf, k32ValueBE);
  comp = big_endian::Load32(&u32Buf);
  EXPECT_EQ(comp, k32Value);

  big_endian::Store64(&u64Buf, k64Value);
  EXPECT_EQ(u64Buf, k64ValueBE);
  comp = big_endian::Load64(&u64Buf);
  EXPECT_EQ(comp, k64Value);

  big_endian::Store16(buffer + 1, k16Value);
  EXPECT_EQ(u16Buf, k16ValueBE);
  comp = big_endian::Load16(buffer + 1);
  EXPECT_EQ(comp, k16Value);

  big_endian::Store32(buffer + 1, k32Value);
  EXPECT_EQ(u32Buf, k32ValueBE);
  comp = big_endian::Load32(buffer + 1);
  EXPECT_EQ(comp, k32Value);

  big_endian::Store64(buffer + 1, k64Value);
  EXPECT_EQ(u64Buf, k64ValueBE);
  comp = big_endian::Load64(buffer + 1);
  EXPECT_EQ(comp, k64Value);
}

}  // namespace
}  // namespace absl
