// Copyright 2019 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/strings/internal/cordz_sample_token.h"

#include <memory>
#include <type_traits>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/memory/memory.h"
#include "absl/random/random.h"
#include "absl/strings/cordz_test_helpers.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/internal/cordz_handle.h"
#include "absl/strings/internal/cordz_info.h"
#include "absl/synchronization/internal/thread_pool.h"
#include "absl/synchronization/notification.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
namespace {

using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::Ne;

// Used test values
auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;

TEST(CordzSampleTokenTest, IteratorTraits) {
  static_assert(std::is_copy_constructible<CordzSampleToken::Iterator>::value,
                "");
  static_assert(std::is_copy_assignable<CordzSampleToken::Iterator>::value, "");
  static_assert(std::is_move_constructible<CordzSampleToken::Iterator>::value,
                "");
  static_assert(std::is_move_assignable<CordzSampleToken::Iterator>::value, "");
  static_assert(
      std::is_same<
          std::iterator_traits<CordzSampleToken::Iterator>::iterator_category,
          std::input_iterator_tag>::value,
      "");
  static_assert(
      std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::value_type,
                   const CordzInfo&>::value,
      "");
  static_assert(
      std::is_same<
          std::iterator_traits<CordzSampleToken::Iterator>::difference_type,
          ptrdiff_t>::value,
      "");
  static_assert(
      std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::pointer,
                   const CordzInfo*>::value,
      "");
  static_assert(
      std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::reference,
                   const CordzInfo&>::value,
      "");
}

TEST(CordzSampleTokenTest, IteratorEmpty) {
  CordzSampleToken token;
  EXPECT_THAT(token.begin(), Eq(token.end()));
}

TEST(CordzSampleTokenTest, Iterator) {
  TestCordData cord1, cord2, cord3;
  CordzInfo::TrackCord(cord1.data, kTrackCordMethod);
  CordzInfo* info1 = cord1.data.cordz_info();
  CordzInfo::TrackCord(cord2.data, kTrackCordMethod);
  CordzInfo* info2 = cord2.data.cordz_info();
  CordzInfo::TrackCord(cord3.data, kTrackCordMethod);
  CordzInfo* info3 = cord3.data.cordz_info();

  CordzSampleToken token;
  std::vector<const CordzInfo*> found;
  for (const CordzInfo& cord_info : token) {
    found.push_back(&cord_info);
  }

  EXPECT_THAT(found, ElementsAre(info3, info2, info1));

  info1->Untrack();
  info2->Untrack();
  info3->Untrack();
}

TEST(CordzSampleTokenTest, IteratorEquality) {
  TestCordData cord1;
  TestCordData cord2;
  TestCordData cord3;
  CordzInfo::TrackCord(cord1.data, kTrackCordMethod);
  CordzInfo* info1 = cord1.data.cordz_info();

  CordzSampleToken token1;
  // lhs starts with the CordzInfo corresponding to cord1 at the head.
  CordzSampleToken::Iterator lhs = token1.begin();

  CordzInfo::TrackCord(cord2.data, kTrackCordMethod);
  CordzInfo* info2 = cord2.data.cordz_info();

  CordzSampleToken token2;
  // rhs starts with the CordzInfo corresponding to cord2 at the head.
  CordzSampleToken::Iterator rhs = token2.begin();

  CordzInfo::TrackCord(cord3.data, kTrackCordMethod);
  CordzInfo* info3 = cord3.data.cordz_info();

  // lhs is on cord1 while rhs is on cord2.
  EXPECT_THAT(lhs, Ne(rhs));

  rhs++;
  // lhs and rhs are both on cord1, but they didn't come from the same
  // CordzSampleToken.
  EXPECT_THAT(lhs, Ne(rhs));

  lhs++;
  rhs++;
  // Both lhs and rhs are done, so they are on nullptr.
  EXPECT_THAT(lhs, Eq(rhs));

  info1->Untrack();
  info2->Untrack();
  info3->Untrack();
}

TEST(CordzSampleTokenTest, MultiThreaded) {
  Notification stop;
  static constexpr int kNumThreads = 4;
  static constexpr int kNumCords = 3;
  static constexpr int kNumTokens = 3;
  absl::synchronization_internal::ThreadPool pool(kNumThreads);

  for (int i = 0; i < kNumThreads; ++i) {
    pool.Schedule([&stop]() {
      absl::BitGen gen;
      TestCordData cords[kNumCords];
      std::unique_ptr<CordzSampleToken> tokens[kNumTokens];

      while (!stop.HasBeenNotified()) {
        // Randomly perform one of five actions:
        //   1) Untrack
        //   2) Track
        //   3) Iterate over Cords visible to a token.
        //   4) Unsample
        //   5) Sample
        int index = absl::Uniform(gen, 0, kNumCords);
        if (absl::Bernoulli(gen, 0.5)) {
          TestCordData& cord = cords[index];
          // Track/untrack.
          if (cord.data.is_profiled()) {
            // 1) Untrack
            cord.data.cordz_info()->Untrack();
            cord.data.clear_cordz_info();
          } else {
            // 2) Track
            CordzInfo::TrackCord(cord.data, kTrackCordMethod);
          }
        } else {
          std::unique_ptr<CordzSampleToken>& token = tokens[index];
          if (token) {
            if (absl::Bernoulli(gen, 0.5)) {
              // 3) Iterate over Cords visible to a token.
              for (const CordzInfo& info : *token) {
                // This is trivial work to allow us to compile the loop.
                EXPECT_THAT(info.Next(*token), Ne(&info));
              }
            } else {
              // 4) Unsample
              token = nullptr;
            }
          } else {
            // 5) Sample
            token = absl::make_unique<CordzSampleToken>();
          }
        }
      }
      for (TestCordData& cord : cords) {
        CordzInfo::MaybeUntrackCord(cord.data.cordz_info());
      }
    });
  }
  // The threads will hammer away.  Give it a little bit of time for tsan to
  // spot errors.
  absl::SleepFor(absl::Seconds(3));
  stop.Notify();
}

}  // namespace
}  // namespace cord_internal
ABSL_NAMESPACE_END
}  // namespace absl
