// 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
//
//      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/internal/explicit_seed_seq.h"

#include <iterator>
#include <random>
#include <utility>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/random/seed_sequences.h"

namespace {

using ::absl::random_internal::ExplicitSeedSeq;

template <typename Sseq>
bool ConformsToInterface() {
  // Check that the SeedSequence can be default-constructed.
  { Sseq default_constructed_seq; }
  // Check that the SeedSequence can be constructed with two iterators.
  {
    uint32_t init_array[] = {1, 3, 5, 7, 9};
    Sseq iterator_constructed_seq(init_array, &init_array[5]);
  }
  // Check that the SeedSequence can be std::initializer_list-constructed.
  { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; }
  // Check that param() and size() return state provided to constructor.
  {
    uint32_t init_array[] = {1, 2, 3, 4, 5};
    Sseq seq(init_array, &init_array[ABSL_ARRAYSIZE(init_array)]);
    EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array));

    uint32_t state_array[ABSL_ARRAYSIZE(init_array)];
    seq.param(state_array);

    for (int i = 0; i < ABSL_ARRAYSIZE(state_array); i++) {
      EXPECT_EQ(state_array[i], i + 1);
    }
  }
  // Check for presence of generate() method.
  {
    Sseq seq;
    uint32_t seeds[5];

    seq.generate(seeds, &seeds[ABSL_ARRAYSIZE(seeds)]);
  }
  return true;
}
}  // namespace

TEST(SeedSequences, CheckInterfaces) {
  // Control case
  EXPECT_TRUE(ConformsToInterface<std::seed_seq>());

  // Abseil classes
  EXPECT_TRUE(ConformsToInterface<ExplicitSeedSeq>());
}

TEST(ExplicitSeedSeq, DefaultConstructorGeneratesZeros) {
  const size_t kNumBlocks = 128;

  uint32_t outputs[kNumBlocks];
  ExplicitSeedSeq seq;
  seq.generate(outputs, &outputs[kNumBlocks]);

  for (uint32_t& seed : outputs) {
    EXPECT_EQ(seed, 0);
  }
}

TEST(ExplicitSeeqSeq, SeedMaterialIsForwardedIdentically) {
  const size_t kNumBlocks = 128;

  uint32_t seed_material[kNumBlocks];
  std::random_device urandom{"/dev/urandom"};
  for (uint32_t& seed : seed_material) {
    seed = urandom();
  }
  ExplicitSeedSeq seq(seed_material, &seed_material[kNumBlocks]);

  // Check that output is same as seed-material provided to constructor.
  {
    const size_t kNumGenerated = kNumBlocks / 2;
    uint32_t outputs[kNumGenerated];
    seq.generate(outputs, &outputs[kNumGenerated]);
    for (size_t i = 0; i < kNumGenerated; i++) {
      EXPECT_EQ(outputs[i], seed_material[i]);
    }
  }
  // Check that SeedSequence is stateless between invocations: Despite the last
  // invocation of generate() only consuming half of the input-entropy, the same
  // entropy will be recycled for the next invocation.
  {
    const size_t kNumGenerated = kNumBlocks;
    uint32_t outputs[kNumGenerated];
    seq.generate(outputs, &outputs[kNumGenerated]);
    for (size_t i = 0; i < kNumGenerated; i++) {
      EXPECT_EQ(outputs[i], seed_material[i]);
    }
  }
  // Check that when more seed-material is asked for than is provided, nonzero
  // values are still written.
  {
    const size_t kNumGenerated = kNumBlocks * 2;
    uint32_t outputs[kNumGenerated];
    seq.generate(outputs, &outputs[kNumGenerated]);
    for (size_t i = 0; i < kNumGenerated; i++) {
      EXPECT_EQ(outputs[i], seed_material[i % kNumBlocks]);
    }
  }
}

TEST(ExplicitSeedSeq, CopyAndMoveConstructors) {
  using testing::Each;
  using testing::Eq;
  using testing::Not;
  using testing::Pointwise;

  uint32_t entropy[4];
  std::random_device urandom("/dev/urandom");
  for (uint32_t& entry : entropy) {
    entry = urandom();
  }
  ExplicitSeedSeq seq_from_entropy(std::begin(entropy), std::end(entropy));
  // Copy constructor.
  {
    ExplicitSeedSeq seq_copy(seq_from_entropy);
    EXPECT_EQ(seq_copy.size(), seq_from_entropy.size());

    std::vector<uint32_t> seeds_1;
    seeds_1.resize(1000, 0);
    std::vector<uint32_t> seeds_2;
    seeds_2.resize(1000, 1);

    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
    seq_copy.generate(seeds_2.begin(), seeds_2.end());

    EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));
  }
  // Assignment operator.
  {
    for (uint32_t& entry : entropy) {
      entry = urandom();
    }
    ExplicitSeedSeq another_seq(std::begin(entropy), std::end(entropy));

    std::vector<uint32_t> seeds_1;
    seeds_1.resize(1000, 0);
    std::vector<uint32_t> seeds_2;
    seeds_2.resize(1000, 0);

    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
    another_seq.generate(seeds_2.begin(), seeds_2.end());

    // Assert precondition: Sequences generated by seed-sequences are not equal.
    EXPECT_THAT(seeds_1, Not(Pointwise(Eq(), seeds_2)));

    // Apply the assignment-operator.
    another_seq = seq_from_entropy;

    // Re-generate seeds.
    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
    another_seq.generate(seeds_2.begin(), seeds_2.end());

    // Seeds generated by seed-sequences should now be equal.
    EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));
  }
  // Move constructor.
  {
    // Get seeds from seed-sequence constructed from entropy.
    std::vector<uint32_t> seeds_1;
    seeds_1.resize(1000, 0);
    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());

    // Apply move-constructor move the sequence to another instance.
    absl::random_internal::ExplicitSeedSeq moved_seq(
        std::move(seq_from_entropy));
    std::vector<uint32_t> seeds_2;
    seeds_2.resize(1000, 1);
    moved_seq.generate(seeds_2.begin(), seeds_2.end());
    // Verify that seeds produced by moved-instance are the same as original.
    EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));

    // Verify that the moved-from instance now behaves like a
    // default-constructed instance.
    EXPECT_EQ(seq_from_entropy.size(), 0);
    seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
    EXPECT_THAT(seeds_1, Each(Eq(0)));
  }
}

TEST(ExplicitSeedSeq, StdURBGGoldenTests) {
  // Verify that for std::- URBG instances the results are stable across
  // platforms (these should have deterministic output).
  {
    ExplicitSeedSeq seed_sequence{12, 34, 56};
    std::minstd_rand rng(seed_sequence);

    std::minstd_rand::result_type values[4] = {rng(), rng(), rng(), rng()};
    EXPECT_THAT(values,
                testing::ElementsAre(579252, 43785881, 464353103, 1501811174));
  }

  {
    ExplicitSeedSeq seed_sequence{12, 34, 56};
    std::mt19937 rng(seed_sequence);

    std::mt19937::result_type values[4] = {rng(), rng(), rng(), rng()};
    EXPECT_THAT(values, testing::ElementsAre(138416803, 151130212, 33817739,
                                             138416803));
  }

  {
    ExplicitSeedSeq seed_sequence{12, 34, 56};
    std::mt19937_64 rng(seed_sequence);

    std::mt19937_64::result_type values[4] = {rng(), rng(), rng(), rng()};
    EXPECT_THAT(values,
                testing::ElementsAre(19738651785169348, 1464811352364190456,
                                     18054685302720800, 19738651785169348));
  }
}
