//
// Copyright 2018 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
//
//      https://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/random/bit_gen_ref.h"

#include <cstdint>
#include <random>
#include <type_traits>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/config.h"
#include "absl/base/fast_type_id.h"
#include "absl/random/internal/sequence_urbg.h"
#include "absl/random/random.h"

namespace absl {
ABSL_NAMESPACE_BEGIN

class ConstBitGen {
 public:
  // URBG interface
  using result_type = absl::BitGen::result_type;

  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
  result_type operator()() { return 1; }

  // InvokeMock method
  bool InvokeMock(FastTypeIdType, void*, void* result) {
    *static_cast<int*>(result) = 42;
    return true;
  }
};

namespace {

int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }

template <typename T>
class BitGenRefTest : public testing::Test {};

using BitGenTypes =
    ::testing::Types<absl::BitGen, absl::InsecureBitGen, std::mt19937,
                     std::mt19937_64, std::minstd_rand>;
TYPED_TEST_SUITE(BitGenRefTest, BitGenTypes);

TYPED_TEST(BitGenRefTest, BasicTest) {
  TypeParam gen;
  auto x = FnTest(gen);
  EXPECT_NEAR(x, 4, 3);
}

TYPED_TEST(BitGenRefTest, Copyable) {
  TypeParam gen;
  absl::BitGenRef gen_ref(gen);
  FnTest(gen_ref);  // Copy
}

TEST(BitGenRefTest, PassThroughEquivalence) {
  // sequence_urbg returns 64-bit results.
  absl::random_internal::sequence_urbg urbg(
      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});

  std::vector<uint64_t> output(12);

  {
    absl::BitGenRef view(urbg);
    for (auto& v : output) {
      v = view();
    }
  }

  std::vector<uint64_t> expected(
      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});

  EXPECT_THAT(output, testing::Eq(expected));
}

TEST(BitGenRefTest, MockingBitGenBaseOverrides) {
  ConstBitGen const_gen;
  EXPECT_EQ(FnTest(const_gen), 42);

  absl::BitGenRef gen_ref(const_gen);
  EXPECT_EQ(FnTest(gen_ref), 42);  // Copy
}

struct MinStdRand {
  // The URBG just returns 0.
  using result_type = absl::BitGen::result_type;
  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
  result_type operator()() { return 0; }

  // Implicit conversions allow passing MinStdRand to functions taking
  // absl::BitGenRef as well as explicitly constructing an absl::BitGenRef from
  // a MinStdRand.
  operator absl::BitGenRef() const {
    conversion_count++;
    return absl::BitGenRef(minstd_gen);
  }

  std::minstd_rand minstd_gen;
  mutable int conversion_count = 0;
};

TEST(BitGenRefTest, IsConvertibleTest) {
  // Verify that MinStdRandBitGen is convertible to absl::BitGenRef.
  EXPECT_TRUE((std::is_convertible_v<MinStdRand, absl::BitGenRef>));

  // Explicit construction should trigger the conversion.
  {
    MinStdRand minstd;
    absl::BitGenRef gen_ref(minstd);
    EXPECT_EQ(minstd.conversion_count, 1);
    (void)gen_ref;
  }

  // Calling a function that accepts absl::BitGenRef should trigger the
  // conversion. This tests implicit conversion.
  {
    MinStdRand minstd;
    auto result = FnTest(minstd);
    EXPECT_EQ(minstd.conversion_count, 1);
    EXPECT_GE(result, 1);
  }
}

}  // namespace
ABSL_NAMESPACE_END
}  // namespace absl
