// 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 {

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<absl::random_internal::ExplicitSeedSeq>());
}

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

  uint32_t outputs[kNumBlocks];
  absl::random_internal::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();
  }
  absl::random_internal::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();
  }
  absl::random_internal::ExplicitSeedSeq seq_from_entropy(std::begin(entropy),
                                                          std::end(entropy));
  // Copy constructor.
  {
    absl::random_internal::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();
    }
    absl::random_internal::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)));
  }
}
