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

#ifndef ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
#define ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_

#include <cstdlib>
#include <ostream>

namespace absl {
inline namespace lts_2018_06_20 {
namespace test_internal {

// A type that counts number of occurences of the type, the live occurrences of
// the type, as well as the number of copies, moves, and swaps that have
// occurred on the type. This is used as a base class for the copyable,
// copyable+movable, and movable types below that are used in actual tests. Use
// InstanceTracker in tests to track the number of instances.
class BaseCountedInstance {
 public:
  explicit BaseCountedInstance(int x) : value_(x) {
    ++num_instances_;
    ++num_live_instances_;
  }
  BaseCountedInstance(const BaseCountedInstance& x)
      : value_(x.value_), is_live_(x.is_live_) {
    ++num_instances_;
    if (is_live_) ++num_live_instances_;
    ++num_copies_;
  }
  BaseCountedInstance(BaseCountedInstance&& x)
      : value_(x.value_), is_live_(x.is_live_) {
    x.is_live_ = false;
    ++num_instances_;
    ++num_moves_;
  }
  ~BaseCountedInstance() {
    --num_instances_;
    if (is_live_) --num_live_instances_;
  }

  BaseCountedInstance& operator=(const BaseCountedInstance& x) {
    value_ = x.value_;
    if (is_live_) --num_live_instances_;
    is_live_ = x.is_live_;
    if (is_live_) ++num_live_instances_;
    ++num_copies_;
    return *this;
  }
  BaseCountedInstance& operator=(BaseCountedInstance&& x) {
    value_ = x.value_;
    if (is_live_) --num_live_instances_;
    is_live_ = x.is_live_;
    x.is_live_ = false;
    ++num_moves_;
    return *this;
  }

  int value() const {
    if (!is_live_) std::abort();
    return value_;
  }

  friend std::ostream& operator<<(std::ostream& o,
                                  const BaseCountedInstance& v) {
    return o << "[value:" << v.value() << "]";
  }

  // Implementation of efficient swap() that counts swaps.
  static void SwapImpl(
      BaseCountedInstance& lhs,    // NOLINT(runtime/references)
      BaseCountedInstance& rhs) {  // NOLINT(runtime/references)
    using std::swap;
    swap(lhs.value_, rhs.value_);
    swap(lhs.is_live_, rhs.is_live_);
    ++BaseCountedInstance::num_swaps_;
  }

 private:
  friend class InstanceTracker;

  int value_;

  // Indicates if the value is live, ie it hasn't been moved away from.
  bool is_live_ = true;

  // Number of instances.
  static int num_instances_;

  // Number of live instances (those that have not been moved away from.)
  static int num_live_instances_;

  // Number of times that BaseCountedInstance objects were moved.
  static int num_moves_;

  // Number of times that BaseCountedInstance objects were copied.
  static int num_copies_;

  // Number of times that BaseCountedInstance objects were swapped.
  static int num_swaps_;
};

// Helper to track the BaseCountedInstance instance counters. Expects that the
// number of instances and live_instances are the same when it is constructed
// and when it is destructed.
class InstanceTracker {
 public:
  InstanceTracker()
      : start_instances_(BaseCountedInstance::num_instances_),
        start_live_instances_(BaseCountedInstance::num_live_instances_) {
    ResetCopiesMovesSwaps();
  }
  ~InstanceTracker() {
    if (instances() != 0) std::abort();
    if (live_instances() != 0) std::abort();
  }

  // Returns the number of BaseCountedInstance instances both containing valid
  // values and those moved away from compared to when the InstanceTracker was
  // constructed
  int instances() const {
    return BaseCountedInstance::num_instances_ - start_instances_;
  }

  // Returns the number of live BaseCountedInstance instances compared to when
  // the InstanceTracker was constructed
  int live_instances() const {
    return BaseCountedInstance::num_live_instances_ - start_live_instances_;
  }

  // Returns the number of moves on BaseCountedInstance objects since
  // construction or since the last call to ResetCopiesMovesSwaps().
  int moves() const { return BaseCountedInstance::num_moves_ - start_moves_; }

  // Returns the number of copies on BaseCountedInstance objects since
  // construction or the last call to ResetCopiesMovesSwaps().
  int copies() const {
    return BaseCountedInstance::num_copies_ - start_copies_;
  }

  // Returns the number of swaps on BaseCountedInstance objects since
  // construction or the last call to ResetCopiesMovesSwaps().
  int swaps() const { return BaseCountedInstance::num_swaps_ - start_swaps_; }

  // Resets the base values for moves, copies and swaps to the current values,
  // so that subsequent Get*() calls for moves, copies and swaps will compare to
  // the situation at the point of this call.
  void ResetCopiesMovesSwaps() {
    start_moves_ = BaseCountedInstance::num_moves_;
    start_copies_ = BaseCountedInstance::num_copies_;
    start_swaps_ = BaseCountedInstance::num_swaps_;
  }

 private:
  int start_instances_;
  int start_live_instances_;
  int start_moves_;
  int start_copies_;
  int start_swaps_;
};

// Copyable, not movable.
class CopyableOnlyInstance : public BaseCountedInstance {
 public:
  explicit CopyableOnlyInstance(int x) : BaseCountedInstance(x) {}
  CopyableOnlyInstance(const CopyableOnlyInstance& rhs) = default;
  CopyableOnlyInstance& operator=(const CopyableOnlyInstance& rhs) = default;

  friend void swap(CopyableOnlyInstance& lhs, CopyableOnlyInstance& rhs) {
    BaseCountedInstance::SwapImpl(lhs, rhs);
  }

  static bool supports_move() { return false; }
};

// Copyable and movable.
class CopyableMovableInstance : public BaseCountedInstance {
 public:
  explicit CopyableMovableInstance(int x) : BaseCountedInstance(x) {}
  CopyableMovableInstance(const CopyableMovableInstance& rhs) = default;
  CopyableMovableInstance(CopyableMovableInstance&& rhs) = default;
  CopyableMovableInstance& operator=(const CopyableMovableInstance& rhs) =
      default;
  CopyableMovableInstance& operator=(CopyableMovableInstance&& rhs) = default;

  friend void swap(CopyableMovableInstance& lhs, CopyableMovableInstance& rhs) {
    BaseCountedInstance::SwapImpl(lhs, rhs);
  }

  static bool supports_move() { return true; }
};

// Only movable, not default-constructible.
class MovableOnlyInstance : public BaseCountedInstance {
 public:
  explicit MovableOnlyInstance(int x) : BaseCountedInstance(x) {}
  MovableOnlyInstance(MovableOnlyInstance&& other) = default;
  MovableOnlyInstance& operator=(MovableOnlyInstance&& other) = default;

  friend void swap(MovableOnlyInstance& lhs, MovableOnlyInstance& rhs) {
    BaseCountedInstance::SwapImpl(lhs, rhs);
  }

  static bool supports_move() { return true; }
};

}  // namespace test_internal
}  // inline namespace lts_2018_06_20
}  // namespace absl

#endif  // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
