#include "absl/memory/memory.h"
#include <sys/types.h>
#include <cstddef>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
namespace {
using ::testing::ElementsAre;
using ::testing::Return;
class DestructorVerifier {
public:
DestructorVerifier() { ++instance_count_; }
DestructorVerifier(const DestructorVerifier&) = delete;
DestructorVerifier& operator=(const DestructorVerifier&) = delete;
~DestructorVerifier() { --instance_count_; }
static int instance_count() { return instance_count_; }
private:
static int instance_count_;
};
int DestructorVerifier::instance_count_ = 0;
TEST(WrapUniqueTest, WrapUnique) {
{
auto dv = new DestructorVerifier;
EXPECT_EQ(1, DestructorVerifier::instance_count());
std::unique_ptr<DestructorVerifier> ptr = absl::WrapUnique(dv);
EXPECT_EQ(1, DestructorVerifier::instance_count());
}
EXPECT_EQ(0, DestructorVerifier::instance_count());
}
TEST(MakeUniqueForOverwriteTest, Basic) {
std::unique_ptr<int> p = absl::make_unique_for_overwrite<int>();
p = absl::make_unique_for_overwrite<int>();
}
struct InitializationVerifier {
static constexpr int kDefaultScalar = 0x43;
static constexpr int kDefaultArray = 0x4B;
static void* operator new(size_t n) {
void* ret = ::operator new(n);
memset(ret, kDefaultScalar, n);
return ret;
}
static void* operator new[](size_t n) {
void* ret = ::operator new[](n);
memset(ret, kDefaultArray, n);
return ret;
}
int a;
int b;
};
TEST(Initialization, MakeUniqueForOverwrite) {
auto p = absl::make_unique_for_overwrite<InitializationVerifier>();
int pattern;
memset(&pattern, InitializationVerifier::kDefaultScalar, sizeof(pattern));
EXPECT_EQ(pattern, p->a);
EXPECT_EQ(pattern, p->b);
}
TEST(Initialization, MakeUniqueForOverwriteArray) {
auto p = absl::make_unique_for_overwrite<InitializationVerifier[]>(2);
int pattern;
memset(&pattern, InitializationVerifier::kDefaultArray, sizeof(pattern));
EXPECT_EQ(pattern, p[0].a);
EXPECT_EQ(pattern, p[0].b);
EXPECT_EQ(pattern, p[1].a);
EXPECT_EQ(pattern, p[1].b);
}
struct ArrayWatch {
void* operator new[](size_t n) {
allocs().push_back(n);
return ::operator new[](n);
}
void operator delete[](void* p) { return ::operator delete[](p); }
static std::vector<size_t>& allocs() {
static auto& v = *new std::vector<size_t>;
return v;
}
};
TEST(MakeUniqueForOverwriteTest, Array) {
ArrayWatch::allocs().clear();
auto p = absl::make_unique_for_overwrite<ArrayWatch[]>(5);
static_assert(std::is_same<decltype(p), std::unique_ptr<ArrayWatch[]>>::value,
"unexpected return type");
EXPECT_THAT(ArrayWatch::allocs(), ElementsAre(5 * sizeof(ArrayWatch)));
}
TEST(RawPtrTest, RawPointer) {
int i = 5;
EXPECT_EQ(&i, absl::RawPtr(&i));
}
TEST(RawPtrTest, SmartPointer) {
int* o = new int(5);
std::unique_ptr<int> p(o);
EXPECT_EQ(o, absl::RawPtr(p));
}
class IntPointerNonConstDeref {
public:
explicit IntPointerNonConstDeref(int* p) : p_(p) {}
friend bool operator!=(const IntPointerNonConstDeref& a, std::nullptr_t) {
return a.p_ != nullptr;
}
int& operator*() { return *p_; }
private:
std::unique_ptr<int> p_;
};
TEST(RawPtrTest, SmartPointerNonConstDereference) {
int* o = new int(5);
IntPointerNonConstDeref p(o);
EXPECT_EQ(o, absl::RawPtr(p));
}
TEST(RawPtrTest, NullValuedRawPointer) {
int* p = nullptr;
EXPECT_EQ(nullptr, absl::RawPtr(p));
}
TEST(RawPtrTest, NullValuedSmartPointer) {
std::unique_ptr<int> p;
EXPECT_EQ(nullptr, absl::RawPtr(p));
}
TEST(RawPtrTest, Nullptr) {
auto p = absl::RawPtr(nullptr);
EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value));
EXPECT_EQ(nullptr, p);
}
TEST(RawPtrTest, Null) {
auto p = absl::RawPtr(nullptr);
EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value));
EXPECT_EQ(nullptr, p);
}
TEST(RawPtrTest, Zero) {
auto p = absl::RawPtr(nullptr);
EXPECT_TRUE((std::is_same<std::nullptr_t, decltype(p)>::value));
EXPECT_EQ(nullptr, p);
}
TEST(ShareUniquePtrTest, Share) {
auto up = absl::make_unique<int>();
int* rp = up.get();
auto sp = absl::ShareUniquePtr(std::move(up));
EXPECT_EQ(sp.get(), rp);
}
TEST(ShareUniquePtrTest, ShareNull) {
struct NeverDie {
using pointer = void*;
void operator()(pointer) {
ASSERT_TRUE(false) << "Deleter should not have been called.";
}
};
std::unique_ptr<void, NeverDie> up;
auto sp = absl::ShareUniquePtr(std::move(up));
}
TEST(WeakenPtrTest, Weak) {
auto sp = std::make_shared<int>();
auto wp = absl::WeakenPtr(sp);
EXPECT_EQ(sp.get(), wp.lock().get());
sp.reset();
EXPECT_TRUE(wp.expired());
}
TEST(AllocatorNoThrowTest, DefaultAllocator) {
#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
EXPECT_TRUE(absl::default_allocator_is_nothrow::value);
#else
EXPECT_FALSE(absl::default_allocator_is_nothrow::value);
#endif
}
TEST(AllocatorNoThrowTest, StdAllocator) {
#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
EXPECT_TRUE(absl::allocator_is_nothrow<std::allocator<int>>::value);
#else
EXPECT_FALSE(absl::allocator_is_nothrow<std::allocator<int>>::value);
#endif
}
TEST(AllocatorNoThrowTest, CustomAllocator) {
struct NoThrowAllocator {
using is_nothrow = std::true_type;
};
struct CanThrowAllocator {
using is_nothrow = std::false_type;
};
struct UnspecifiedAllocator {};
EXPECT_TRUE(absl::allocator_is_nothrow<NoThrowAllocator>::value);
EXPECT_FALSE(absl::allocator_is_nothrow<CanThrowAllocator>::value);
EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value);
}
}