// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/lib/callback/auto_cleanable.h"

#include <lib/async-testing/test_loop.h>
#include <lib/fit/function.h>
#include <zircon/compiler.h>

#include <gtest/gtest.h>

namespace callback {
namespace {

class Cleanable {
 public:
  explicit Cleanable(int id = 0) : id(id) {}
  void SetOnDiscardable(fit::closure on_discardable) {
    on_discardable_ = std::move(on_discardable);
  }

  bool IsDiscardable() const { return cleaned; }

  void Clean() {
    cleaned = true;
    if (on_discardable_)
      on_discardable_();
  }

  int id;
  bool cleaned = false;

 private:
  fit::closure on_discardable_;
};

TEST(AutoCleanableSet, ClearsOnDiscardable) {
  async::TestLoop loop;

  AutoCleanableSet<Cleanable> set(loop.dispatcher());
  EXPECT_TRUE(set.empty());
  EXPECT_EQ(0UL, set.size());

  auto& p1 = set.emplace();
  auto& p2 = set.emplace();

  EXPECT_FALSE(set.empty());
  EXPECT_EQ(2UL, set.size());

  p1.Clean();

  loop.RunUntilIdle();
  EXPECT_FALSE(set.empty());
  EXPECT_EQ(1UL, set.size());

  p2.Clean();

  loop.RunUntilIdle();
  EXPECT_TRUE(set.empty());
  EXPECT_EQ(0UL, set.size());
}

TEST(AutoCleanableSet, Iterator) {
  async::TestLoop loop;

  AutoCleanableSet<Cleanable> set(loop.dispatcher());
  EXPECT_TRUE(set.empty());

  auto& p1 = set.emplace(1);
  auto& p2 = set.emplace(2);
  auto& p3 = set.emplace(3);
  auto& p4 = set.emplace(4);
  EXPECT_FALSE(set.empty());
  EXPECT_EQ(4UL, set.size());
  p2.Clean();
  loop.RunUntilIdle();

  AutoCleanableSet<Cleanable>::iterator it = set.begin();
  std::unordered_set<int> expected_ids{p1.id, p3.id, p4.id};

  // Test postfix increment
  std::unordered_set<int> actual_ids{it++->id, it++->id, it++->id};
  EXPECT_EQ(expected_ids, actual_ids);

  EXPECT_EQ(set.end(), it);

  it = set.begin();
  actual_ids.clear();

  // Test prefix increment
  actual_ids.insert(it->id);
  actual_ids.insert((++it)->id);
  actual_ids.insert((++it)->id);
  ++it;
  EXPECT_EQ(expected_ids, actual_ids);

  EXPECT_EQ(set.end(), it);
}

TEST(AutoCleanableSet, CallsOnDiscardable) {
  async::TestLoop loop;

  AutoCleanableSet<Cleanable> set(loop.dispatcher());
  bool discardable_called = false;
  set.SetOnDiscardable([&discardable_called] { discardable_called = true; });

  EXPECT_FALSE(discardable_called);

  auto& p1 = set.emplace();
  EXPECT_FALSE(discardable_called);

  p1.Clean();
  loop.RunUntilIdle();
  EXPECT_TRUE(discardable_called);
}

TEST(AutoCleanableMap, ClearsOnDiscardable) {
  async::TestLoop loop;

  AutoCleanableMap<int, Cleanable> map(loop.dispatcher());
  EXPECT_TRUE(map.empty());

  auto& p1 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple())
          .first->second;
  auto& p2 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple())
          .first->second;

  EXPECT_FALSE(map.empty());

  p1.Clean();
  loop.RunUntilIdle();
  EXPECT_FALSE(map.empty());

  p2.Clean();
  loop.RunUntilIdle();
  EXPECT_TRUE(map.empty());
}

TEST(AutoCleanableMap, CallsOnDiscardable) {
  async::TestLoop loop;

  AutoCleanableMap<int, Cleanable> map(loop.dispatcher());
  bool discardable_called = false;
  map.SetOnDiscardable([&discardable_called] { discardable_called = true; });

  EXPECT_FALSE(discardable_called);

  auto& p1 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple())
          .first->second;
  EXPECT_FALSE(discardable_called);

  p1.Clean();
  loop.RunUntilIdle();
  EXPECT_TRUE(discardable_called);
}

TEST(AutoCleanableMap, GetSize) {
  async::TestLoop loop;

  AutoCleanableMap<int, Cleanable> map(loop.dispatcher());

  EXPECT_EQ(0u, map.size());

  auto& p1 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple())
          .first->second;
  EXPECT_EQ(1u, map.size());

  auto& p2 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple())
          .first->second;

  auto& p3 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple())
          .first->second;

  EXPECT_EQ(3u, map.size());

  p1.Clean();
  p2.Clean();
  p3.Clean();
  loop.RunUntilIdle();
  EXPECT_EQ(0u, map.size());
}

TEST(AutoCleanableMap, GetBegin) {
  async::TestLoop loop;

  AutoCleanableMap<int, Cleanable> map(loop.dispatcher());

  const auto& p1 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple())
          .first;

  const auto& p2 =
      map.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple())
          .first;

  const AutoCleanableMap<int, Cleanable>::iterator it1 = map.begin();

  EXPECT_EQ(it1, p1);

  EXPECT_NE(it1, p2);

  p1->second.Clean();
  loop.RunUntilIdle();

  EXPECT_EQ(map.begin(), p2);

  p2->second.Clean();
  loop.RunUntilIdle();

  EXPECT_EQ(map.begin(), map.end());
}

TEST(AutoCleanableMap, ConstIteration) {
  async::TestLoop loop;

  const AutoCleanableMap<int, Cleanable> map(loop.dispatcher());
  for (__UNUSED const auto& [key, value] : map) {
  }
}

TEST(AutoCleanableMap, Clear) {
  async::TestLoop loop;

  AutoCleanableMap<int, Cleanable> map(loop.dispatcher());
  map.emplace(std::piecewise_construct, std::forward_as_tuple(0), std::forward_as_tuple());
  map.emplace(std::piecewise_construct, std::forward_as_tuple(1), std::forward_as_tuple());
  map.emplace(std::piecewise_construct, std::forward_as_tuple(2), std::forward_as_tuple());

  EXPECT_FALSE(map.empty());

  map.clear();

  EXPECT_TRUE(map.empty());
}

}  // namespace
}  // namespace callback
