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

#include "absl/container/node_hash_map.h"

#include "absl/container/internal/tracked.h"
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
#include "absl/container/internal/unordered_map_modifiers_test.h"

namespace absl {
namespace container_internal {
namespace {

using ::testing::Field;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;

using MapTypes = ::testing::Types<
    absl::node_hash_map<int, int, StatefulTestingHash, StatefulTestingEqual,
                        Alloc<std::pair<const int, int>>>,
    absl::node_hash_map<std::string, std::string, StatefulTestingHash,
                        StatefulTestingEqual,
                        Alloc<std::pair<const std::string, std::string>>>>;

INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ConstructorTest, MapTypes);
INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, LookupTest, MapTypes);
INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ModifiersTest, MapTypes);

using M = absl::node_hash_map<std::string, Tracked<int>>;

TEST(NodeHashMap, Emplace) {
  M m;
  Tracked<int> t(53);
  m.emplace("a", t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(1, t.num_copies());

  m.emplace(std::string("a"), t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(1, t.num_copies());

  std::string a("a");
  m.emplace(a, t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(1, t.num_copies());

  const std::string ca("a");
  m.emplace(a, t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(1, t.num_copies());

  m.emplace(std::make_pair("a", t));
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(2, t.num_copies());

  m.emplace(std::make_pair(std::string("a"), t));
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(3, t.num_copies());

  std::pair<std::string, Tracked<int>> p("a", t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(4, t.num_copies());
  m.emplace(p);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(4, t.num_copies());

  const std::pair<std::string, Tracked<int>> cp("a", t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(5, t.num_copies());
  m.emplace(cp);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(5, t.num_copies());

  std::pair<const std::string, Tracked<int>> pc("a", t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(6, t.num_copies());
  m.emplace(pc);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(6, t.num_copies());

  const std::pair<const std::string, Tracked<int>> cpc("a", t);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(7, t.num_copies());
  m.emplace(cpc);
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(7, t.num_copies());

  m.emplace(std::piecewise_construct, std::forward_as_tuple("a"),
            std::forward_as_tuple(t));
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(7, t.num_copies());

  m.emplace(std::piecewise_construct, std::forward_as_tuple(std::string("a")),
            std::forward_as_tuple(t));
  ASSERT_EQ(0, t.num_moves());
  ASSERT_EQ(7, t.num_copies());
}

TEST(NodeHashMap, AssignRecursive) {
  struct Tree {
    // Verify that unordered_map<K, IncompleteType> can be instantiated.
    absl::node_hash_map<int, Tree> children;
  };
  Tree root;
  const Tree& child = root.children.emplace().first->second;
  // Verify that `lhs = rhs` doesn't read rhs after clearing lhs.
  root = child;
}

TEST(FlatHashMap, MoveOnlyKey) {
  struct Key {
    Key() = default;
    Key(Key&&) = default;
    Key& operator=(Key&&) = default;
  };
  struct Eq {
    bool operator()(const Key&, const Key&) const { return true; }
  };
  struct Hash {
    size_t operator()(const Key&) const { return 0; }
  };
  absl::node_hash_map<Key, int, Hash, Eq> m;
  m[Key()];
}

struct NonMovableKey {
  explicit NonMovableKey(int i) : i(i) {}
  NonMovableKey(NonMovableKey&&) = delete;
  int i;
};
struct NonMovableKeyHash {
  using is_transparent = void;
  size_t operator()(const NonMovableKey& k) const { return k.i; }
  size_t operator()(int k) const { return k; }
};
struct NonMovableKeyEq {
  using is_transparent = void;
  bool operator()(const NonMovableKey& a, const NonMovableKey& b) const {
    return a.i == b.i;
  }
  bool operator()(const NonMovableKey& a, int b) const { return a.i == b; }
};

TEST(NodeHashMap, MergeExtractInsert) {
  absl::node_hash_map<NonMovableKey, int, NonMovableKeyHash, NonMovableKeyEq>
      set1, set2;
  set1.emplace(std::piecewise_construct, std::make_tuple(7),
               std::make_tuple(-7));
  set1.emplace(std::piecewise_construct, std::make_tuple(17),
               std::make_tuple(-17));

  set2.emplace(std::piecewise_construct, std::make_tuple(7),
               std::make_tuple(-70));
  set2.emplace(std::piecewise_construct, std::make_tuple(19),
               std::make_tuple(-190));

  auto Elem = [](int key, int value) {
    return Pair(Field(&NonMovableKey::i, key), value);
  };

  EXPECT_THAT(set1, UnorderedElementsAre(Elem(7, -7), Elem(17, -17)));
  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(19, -190)));

  // NonMovableKey is neither copyable nor movable. We should still be able to
  // move nodes around.
  static_assert(!std::is_move_constructible<NonMovableKey>::value, "");
  set1.merge(set2);

  EXPECT_THAT(set1,
              UnorderedElementsAre(Elem(7, -7), Elem(17, -17), Elem(19, -190)));
  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70)));

  auto node = set1.extract(7);
  EXPECT_TRUE(node);
  EXPECT_EQ(node.key().i, 7);
  EXPECT_EQ(node.mapped(), -7);
  EXPECT_THAT(set1, UnorderedElementsAre(Elem(17, -17), Elem(19, -190)));

  auto insert_result = set2.insert(std::move(node));
  EXPECT_FALSE(node);
  EXPECT_FALSE(insert_result.inserted);
  EXPECT_TRUE(insert_result.node);
  EXPECT_EQ(insert_result.node.key().i, 7);
  EXPECT_EQ(insert_result.node.mapped(), -7);
  EXPECT_THAT(*insert_result.position, Elem(7, -70));
  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70)));

  node = set1.extract(17);
  EXPECT_TRUE(node);
  EXPECT_EQ(node.key().i, 17);
  EXPECT_EQ(node.mapped(), -17);
  EXPECT_THAT(set1, UnorderedElementsAre(Elem(19, -190)));

  node.mapped() = 23;

  insert_result = set2.insert(std::move(node));
  EXPECT_FALSE(node);
  EXPECT_TRUE(insert_result.inserted);
  EXPECT_FALSE(insert_result.node);
  EXPECT_THAT(*insert_result.position, Elem(17, 23));
  EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(17, 23)));
}

}  // namespace
}  // namespace container_internal
}  // namespace absl
