blob: 92cf2949f7aceb6d4a02318300190625131b0259 [file] [log] [blame]
// Copyright 2017 PDFium 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 "core/fxcrt/unowned_ptr.h"
#include <functional>
#include <memory>
#include <set>
#include <utility>
#include "testing/gtest/include/gtest/gtest.h"
namespace fxcrt {
namespace {
template <typename T, typename C = std::less<T>>
class NoLinearSearchSet : public std::set<T, C> {
public:
typename std::set<T, C>::iterator begin() noexcept = delete;
typename std::set<T, C>::const_iterator cbegin() const noexcept = delete;
};
class Clink {
public:
UnownedPtr<Clink> next_ = nullptr;
};
void DeleteDangling() {
auto ptr2 = std::make_unique<Clink>();
{
auto ptr1 = std::make_unique<Clink>();
ptr2->next_ = ptr1.get();
}
}
void ResetDangling() {
auto ptr2 = std::make_unique<Clink>();
{
auto ptr1 = std::make_unique<Clink>();
ptr2->next_.Reset(ptr1.get());
}
ptr2->next_.Reset();
}
void AssignDangling() {
auto ptr2 = std::make_unique<Clink>();
{
auto ptr1 = std::make_unique<Clink>();
ptr2->next_ = ptr1.get();
}
ptr2->next_ = nullptr;
}
void ReleaseDangling() {
auto ptr2 = std::make_unique<Clink>();
{
auto ptr1 = std::make_unique<Clink>();
ptr2->next_ = ptr1.get();
}
ptr2->next_.Release();
}
} // namespace
TEST(UnownedPtr, PtrOk) {
auto ptr1 = std::make_unique<Clink>();
{
auto ptr2 = std::make_unique<Clink>();
ptr2->next_ = ptr1.get();
}
}
TEST(UnownedPtr, PtrNotOk) {
#if defined(ADDRESS_SANITIZER)
EXPECT_DEATH(DeleteDangling(), "");
#else
DeleteDangling();
#endif
}
TEST(UnownedPtr, ResetOk) {
auto ptr1 = std::make_unique<Clink>();
{
auto ptr2 = std::make_unique<Clink>();
ptr2->next_.Reset(ptr1.get());
ptr2->next_.Reset(nullptr);
}
}
TEST(UnownedPtr, ResetNotOk) {
#if defined(ADDRESS_SANITIZER)
EXPECT_DEATH(ResetDangling(), "");
#else
ResetDangling();
#endif
}
TEST(UnownedPtr, AssignOk) {
auto ptr1 = std::make_unique<Clink>();
{
auto ptr2 = std::make_unique<Clink>();
ptr2->next_ = ptr1.get();
ptr2->next_ = nullptr;
}
}
TEST(UnownedPtr, AssignNotOk) {
#if defined(ADDRESS_SANITIZER)
EXPECT_DEATH(AssignDangling(), "");
#else
AssignDangling();
#endif
}
TEST(UnownedPtr, ReleaseOk) {
auto ptr2 = std::make_unique<Clink>();
{
auto ptr1 = std::make_unique<Clink>();
ptr2->next_ = ptr1.get();
ptr2->next_.Release();
}
}
TEST(UnownedPtr, MoveCtorOk) {
UnownedPtr<Clink> outer;
{
auto owned = std::make_unique<Clink>();
outer = owned.get();
UnownedPtr<Clink> inner(std::move(outer));
EXPECT_FALSE(outer.Get());
}
}
TEST(UnownedPtr, MoveAssignOk) {
UnownedPtr<Clink> outer;
{
auto owned = std::make_unique<Clink>();
outer = owned.get();
UnownedPtr<Clink> inner;
inner = std::move(outer);
EXPECT_FALSE(outer.Get());
}
}
TEST(UnownedPtr, ReleaseNotOk) {
#if defined(ADDRESS_SANITIZER)
EXPECT_DEATH(ReleaseDangling(), "");
#else
ReleaseDangling();
#endif
}
TEST(UnownedPtr, OperatorEQ) {
int foo;
UnownedPtr<int> ptr1;
EXPECT_TRUE(ptr1 == ptr1);
UnownedPtr<int> ptr2;
EXPECT_TRUE(ptr1 == ptr2);
UnownedPtr<int> ptr3(&foo);
EXPECT_TRUE(&foo == ptr3);
EXPECT_TRUE(ptr3 == &foo);
EXPECT_FALSE(ptr1 == ptr3);
ptr1 = &foo;
EXPECT_TRUE(ptr1 == ptr3);
}
TEST(UnownedPtr, OperatorNE) {
int foo;
UnownedPtr<int> ptr1;
EXPECT_FALSE(ptr1 != ptr1);
UnownedPtr<int> ptr2;
EXPECT_FALSE(ptr1 != ptr2);
UnownedPtr<int> ptr3(&foo);
EXPECT_FALSE(&foo != ptr3);
EXPECT_FALSE(ptr3 != &foo);
EXPECT_TRUE(ptr1 != ptr3);
ptr1 = &foo;
EXPECT_FALSE(ptr1 != ptr3);
}
TEST(UnownedPtr, OperatorLT) {
int foos[2];
UnownedPtr<int> ptr1(&foos[0]);
UnownedPtr<int> ptr2(&foos[1]);
EXPECT_FALSE(ptr1 < ptr1);
EXPECT_TRUE(ptr1 < ptr2);
EXPECT_FALSE(ptr2 < ptr1);
}
TEST(UnownedPtr, TransparentCompare) {
int foos[2];
UnownedPtr<int> ptr1(&foos[0]);
UnownedPtr<int> ptr2(&foos[1]);
NoLinearSearchSet<UnownedPtr<int>, std::less<>> holder;
holder.insert(ptr1);
EXPECT_NE(holder.end(), holder.find(&foos[0]));
EXPECT_EQ(holder.end(), holder.find(&foos[1]));
}
} // namespace fxcrt