/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 <atomic>
#include <mutex>
#include <unordered_map>

#include <gtest/gtest.h>

#include "TestableRecursiveMutex.hpp"
#include "util/synchronized_map.hpp"

using apache::geode::client::synchronized_map;

TEST(synchronized_mapTest, emplaceLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  auto result = map.emplace("a", "A");
  ASSERT_EQ(true, result.second);
  EXPECT_EQ("a", result.first->first);
  EXPECT_EQ("A", result.first->second);
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);

  result = map.emplace("b", "B");
  ASSERT_EQ(true, result.second);
  EXPECT_EQ("b", result.first->first);
  EXPECT_EQ("B", result.first->second);
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(2, map.mutex().lock_count_);
  EXPECT_EQ(2, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, eraseKeyLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  auto result = map.erase("a");
  ASSERT_EQ(1, result);
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, beginLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  const auto& begin = map.begin();

  ASSERT_EQ("a", begin->first);

  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, beginConstLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  const auto& constMap = map;
  const auto& begin = constMap.begin();

  ASSERT_EQ("a", begin->first);

  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, cbeginLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  const auto& begin = map.cbegin();

  ASSERT_EQ("a", begin->first);

  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, endLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  const auto& begin = map.begin();
  const auto& end = map.end();

  ASSERT_NE(begin, end);

  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, endConsLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  const auto& constMap = map;
  const auto& begin = constMap.begin();
  const auto& end = constMap.end();

  ASSERT_NE(begin, end);

  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, cendLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  const auto& begin = map.cbegin();
  const auto& end = map.cend();

  ASSERT_NE(begin, end);

  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, emptyLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  ASSERT_TRUE(map.empty());
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);

  map.emplace("a", "A");
  map.mutex().resetCounters();

  ASSERT_FALSE(map.empty());
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, sizeLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  ASSERT_EQ(0, map.size());
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);

  map.emplace("a", "A");
  map.mutex().resetCounters();

  ASSERT_EQ(1, map.size());
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, clearLocks) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  map.clear();
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
  EXPECT_TRUE(map.empty());
}

TEST(synchronized_mapTest, findNotLocked) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  {
    std::lock_guard<decltype(map)::mutex_type> lock(map.mutex());
    const auto& entry = map.find("a");
    EXPECT_EQ(1, map.mutex().recursive_depth_);
    EXPECT_EQ(1, map.mutex().lock_count_);
    EXPECT_EQ(0, map.mutex().unlock_count_);
    EXPECT_EQ("a", entry->first);
  }
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, findConstNotLocked) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.mutex().resetCounters();

  {
    auto&& lock = map.make_lock();
    const auto& constMap = map;
    const auto& entry = constMap.find("a");
    EXPECT_EQ(1, map.mutex().recursive_depth_);
    EXPECT_EQ(1, map.mutex().lock_count_);
    EXPECT_EQ(0, map.mutex().unlock_count_);
    EXPECT_EQ("a", entry->first);
  }
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, iteratorNotLocked) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.emplace("a", "A");
  map.emplace("b", "B");
  map.mutex().resetCounters();

  auto& mutex = map.mutex();
  EXPECT_EQ(0, mutex.recursive_depth_);
  EXPECT_EQ(0, mutex.recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);

  {
    for (const auto& entry : map) {
      EXPECT_EQ(0, mutex.recursive_depth_);
      EXPECT_EQ(0, map.mutex().lock_count_);
      EXPECT_EQ(0, map.mutex().unlock_count_);
    }
  }
  EXPECT_EQ(0, mutex.recursive_depth_);
  EXPECT_EQ(0, map.mutex().lock_count_);
  EXPECT_EQ(0, map.mutex().unlock_count_);

  {
    std::lock_guard<decltype(map)::mutex_type> lock(mutex);
    for (const auto& entry : map) {
      EXPECT_EQ(1, mutex.recursive_depth_);
      EXPECT_EQ(1, map.mutex().lock_count_);
      EXPECT_EQ(0, map.mutex().unlock_count_);
    }
  }
  EXPECT_EQ(0, mutex.recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, make_lockDefault) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  {
    auto&& lock = map.make_lock();
    EXPECT_EQ(1, map.mutex().recursive_depth_);
    EXPECT_EQ(1, map.mutex().lock_count_);
    EXPECT_EQ(0, map.mutex().unlock_count_);
  }
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, make_lock_WithUniqueLock) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  {
    auto&& lock = map.make_lock<std::unique_lock>();
    EXPECT_EQ(1, map.mutex().recursive_depth_);
    EXPECT_EQ(1, map.mutex().lock_count_);
    EXPECT_EQ(0, map.mutex().unlock_count_);
  }
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, make_lock_WithUniqueLockDefered) {
  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  {
    auto&& lock = map.make_lock<std::unique_lock>(std::defer_lock);
    EXPECT_EQ(0, map.mutex().recursive_depth_);
    EXPECT_EQ(0, map.mutex().lock_count_);
    EXPECT_EQ(0, map.mutex().unlock_count_);
    lock.lock();
    EXPECT_EQ(1, map.mutex().recursive_depth_);
    EXPECT_EQ(1, map.mutex().lock_count_);
    EXPECT_EQ(0, map.mutex().unlock_count_);
  }
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
}

TEST(synchronized_mapTest, insertIteratorIteratorLocks) {
  std::unordered_map<std::string, std::string> source = {{"a", "A"},
                                                         {"b", "B"}};

  synchronized_map<std::unordered_map<std::string, std::string>,
                   TestableRecursiveMutex>
      map;

  map.insert(source.begin(), source.end());
  EXPECT_EQ(0, map.mutex().recursive_depth_);
  EXPECT_EQ(1, map.mutex().lock_count_);
  EXPECT_EQ(1, map.mutex().unlock_count_);
  EXPECT_EQ(2, map.size());
}
