/*
    This file is part of TON Blockchain Library.
    TON Blockchain Library is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.
    TON Blockchain Library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.
    You should have received a copy of the GNU Lesser General Public License
    along with TON Blockchain Library.  If not, see .
    Copyright 2017-2020 Telegram Systems LLP
*/
#include "td/utils/common.h"
#include "td/utils/SharedObjectPool.h"
#include "td/utils/tests.h"
#include 
TEST(AtomicRefCnt, simple) {
  td::detail::AtomicRefCnt cnt{0};
  cnt.inc();
  cnt.inc();
  CHECK(!cnt.dec());
  cnt.inc();
  CHECK(!cnt.dec());
  CHECK(cnt.dec());
  cnt.inc();
  CHECK(cnt.dec());
}
template 
using Ptr = td::detail::SharedPtr;
class Deleter {
 public:
  template 
  void operator()(T *t) {
    std::default_delete()(t);
    was_delete() = true;
  }
  static bool &was_delete() {
    static bool flag = false;
    return flag;
  }
};
TEST(SharedPtr, simple) {
  CHECK(!Deleter::was_delete());
  Ptr ptr = Ptr::create("hello");
  auto ptr2 = ptr;
  CHECK(*ptr == "hello");
  CHECK(*ptr2 == "hello");
  ptr.reset();
  CHECK(*ptr2 == "hello");
  CHECK(ptr.empty());
  Ptr ptr3 = std::move(ptr2);
  CHECK(ptr2.empty());
  CHECK(*ptr3 == "hello");
  ptr = ptr3;
  CHECK(*ptr3 == "hello");
  ptr3.reset();
  CHECK(*ptr == "hello");
  ptr2 = std::move(ptr);
  CHECK(ptr.empty());
  CHECK(*ptr2 == "hello");
#if TD_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wunknown-warning-option"
#pragma clang diagnostic ignored "-Wself-assign-overloaded"
#endif
  ptr2 = ptr2;
#if TD_CLANG
#pragma clang diagnostic pop
#endif
  CHECK(*ptr2 == "hello");
  CHECK(!Deleter::was_delete());
  ptr2.reset();
  CHECK(Deleter::was_delete());
  CHECK(ptr2.empty());
}
TEST(SharedObjectPool, simple) {
  class Node {
   public:
    Node() {
      cnt()++;
    };
    ~Node() {
      cnt()--;
    }
    static int &cnt() {
      static int cnt_ = 0;
      return cnt_;
    }
  };
  {
    td::SharedObjectPool pool;
    { auto ptr1 = pool.alloc(); }
    { auto ptr2 = pool.alloc(); }
    { auto ptr3 = pool.alloc(); }
    { auto ptr4 = pool.alloc(); }
    { auto ptr5 = pool.alloc(); }
    CHECK(Node::cnt() == 0);
    CHECK(pool.total_size() == 1);
    CHECK(pool.calc_free_size() == 1);
    { auto ptr6 = pool.alloc(), ptr7 = pool.alloc(), ptr8 = pool.alloc(); }
    CHECK(pool.total_size() == 3);
    CHECK(pool.calc_free_size() == 3);
  }
  CHECK(Node::cnt() == 0);
}