|  | // Copyright 2020 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 <lib/fidl/llcpp/unowned_ptr.h> | 
|  |  | 
|  | #include <unordered_set> | 
|  |  | 
|  | #include <gtest/gtest.h> | 
|  |  | 
|  | TEST(UnownedPtr, Constructor) { | 
|  | int32_t val = 1; | 
|  | fidl::unowned_ptr_t<int32_t> a(&val); | 
|  | EXPECT_EQ(a.get(), &val); | 
|  | fidl::unowned_ptr_t<int32_t> b(a); | 
|  | EXPECT_EQ(a.get(), &val); | 
|  | EXPECT_EQ(b.get(), &val); | 
|  | fidl::unowned_ptr_t<int32_t> c(nullptr); | 
|  | EXPECT_EQ(c.get(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, VoidConstructor) { | 
|  | int32_t val = 1; | 
|  | void* vptr = &val; | 
|  | fidl::unowned_ptr_t<void> a(vptr); | 
|  | EXPECT_EQ(a.get(), vptr); | 
|  | fidl::unowned_ptr_t<void> b(a); | 
|  | EXPECT_EQ(a.get(), vptr); | 
|  | EXPECT_EQ(b.get(), vptr); | 
|  | fidl::unowned_ptr_t<void> c(nullptr); | 
|  | EXPECT_EQ(c.get(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Destructor) { | 
|  | struct DestructableObject { | 
|  | ~DestructableObject() { *destructor_called = true; } | 
|  | bool* destructor_called; | 
|  | }; | 
|  |  | 
|  | bool destructor_called = false; | 
|  | DestructableObject x{.destructor_called = &destructor_called}; | 
|  | { fidl::unowned_ptr_t<DestructableObject> ptr(&x); } | 
|  | EXPECT_FALSE(destructor_called); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Assignment) { | 
|  | int32_t val1 = 1, val2 = 2; | 
|  | fidl::unowned_ptr_t<int32_t> a(&val1); | 
|  | EXPECT_EQ(a.get(), &val1); | 
|  | fidl::unowned_ptr_t<int32_t> b(&val2); | 
|  | EXPECT_EQ(b.get(), &val2); | 
|  | b = a; | 
|  | EXPECT_EQ(a.get(), &val1); | 
|  | EXPECT_EQ(b.get(), &val1); | 
|  | b = std::move(a); | 
|  | EXPECT_EQ(a.get(), &val1); | 
|  | EXPECT_EQ(b.get(), &val1); | 
|  | b = &val2; | 
|  | EXPECT_EQ(b.get(), &val2); | 
|  | b = nullptr; | 
|  | EXPECT_EQ(b.get(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, VoidAssignment) { | 
|  | int32_t val1 = 1, val2 = 2; | 
|  | void* vptr1 = &val1; | 
|  | void* vptr2 = &val2; | 
|  | fidl::unowned_ptr_t<void> a(vptr1); | 
|  | EXPECT_EQ(a.get(), vptr1); | 
|  | fidl::unowned_ptr_t<void> b(vptr2); | 
|  | EXPECT_EQ(b.get(), vptr2); | 
|  | b = a; | 
|  | EXPECT_EQ(a.get(), vptr1); | 
|  | EXPECT_EQ(b.get(), vptr1); | 
|  | b = vptr2; | 
|  | EXPECT_EQ(b.get(), vptr2); | 
|  | b = nullptr; | 
|  | EXPECT_EQ(b.get(), nullptr); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, OperatorBool) { | 
|  | fidl::unowned_ptr_t<int32_t> default_ptr; | 
|  | EXPECT_FALSE(default_ptr); | 
|  | int32_t val = 1; | 
|  | fidl::unowned_ptr_t<int32_t> ptr(&val); | 
|  | EXPECT_TRUE(ptr); | 
|  | ptr = nullptr; | 
|  | EXPECT_FALSE(ptr); | 
|  | ptr = reinterpret_cast<int32_t*>(0); | 
|  | EXPECT_FALSE(ptr); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Dereference) { | 
|  | struct TestStruct { | 
|  | int a; | 
|  | }; | 
|  | TestStruct example{.a = 1}; | 
|  | fidl::unowned_ptr_t<TestStruct> example_ptr(&example); | 
|  | EXPECT_EQ((*example_ptr).a, 1); | 
|  | EXPECT_EQ(example_ptr->a, 1); | 
|  | *example_ptr = TestStruct{.a = 2}; | 
|  | EXPECT_EQ(example_ptr->a, 2); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Indexing) { | 
|  | int32_t arr[3] = {1, 2, 3}; | 
|  | fidl::unowned_ptr_t<int32_t> ptr(arr); | 
|  | EXPECT_EQ(ptr[1], 2); | 
|  | ptr[0] = 4; | 
|  | EXPECT_EQ(ptr[0], 4); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Swap) { | 
|  | int32_t x, y; | 
|  | fidl::unowned_ptr_t<int32_t> x_ptr(&x); | 
|  | fidl::unowned_ptr_t<int32_t> y_ptr(&y); | 
|  | std::swap(x_ptr, y_ptr); | 
|  | EXPECT_EQ(x_ptr.get(), &y); | 
|  | EXPECT_EQ(y_ptr.get(), &x); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Hashing) { | 
|  | int32_t val; | 
|  | fidl::unowned_ptr_t<int32_t> ptr(&val); | 
|  | EXPECT_EQ(std::hash<fidl::unowned_ptr_t<int32_t>>{}(ptr), std::hash<int32_t*>{}(&val)); | 
|  |  | 
|  | // Ensure that hashing is correctly implemented so unordered_set can be used. | 
|  | std::unordered_set<fidl::unowned_ptr_t<int32_t>> set; | 
|  | set.insert(ptr); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Comparison) { | 
|  | int32_t* lower_ptr = reinterpret_cast<int32_t*>(1); | 
|  | int32_t* upper_ptr = reinterpret_cast<int32_t*>(2); | 
|  | fidl::unowned_ptr_t<int32_t> lower(lower_ptr); | 
|  | fidl::unowned_ptr_t<int32_t> lower2(lower_ptr); | 
|  | fidl::unowned_ptr_t<int32_t> upper(upper_ptr); | 
|  |  | 
|  | EXPECT_TRUE(lower == lower2); | 
|  | EXPECT_FALSE(lower == upper); | 
|  | EXPECT_TRUE(lower != upper); | 
|  | EXPECT_FALSE(lower != lower2); | 
|  | EXPECT_TRUE(lower < upper); | 
|  | EXPECT_FALSE(lower < lower); | 
|  | EXPECT_FALSE(upper < lower); | 
|  | EXPECT_TRUE(lower <= upper); | 
|  | EXPECT_TRUE(lower <= lower); | 
|  | EXPECT_FALSE(upper <= lower); | 
|  | EXPECT_TRUE(upper > lower); | 
|  | EXPECT_FALSE(upper > upper); | 
|  | EXPECT_FALSE(lower > upper); | 
|  | EXPECT_TRUE(upper >= lower); | 
|  | EXPECT_TRUE(upper >= upper); | 
|  | EXPECT_FALSE(lower >= upper); | 
|  |  | 
|  | EXPECT_FALSE(lower == nullptr); | 
|  | EXPECT_FALSE(nullptr == lower); | 
|  | EXPECT_TRUE(lower != nullptr); | 
|  | EXPECT_TRUE(nullptr != lower); | 
|  |  | 
|  | // Ensure that comparison is correctly implemented so set can be used. | 
|  | std::set<fidl::unowned_ptr_t<int32_t>> set; | 
|  | set.insert(lower); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Const) { | 
|  | int32_t val = 1; | 
|  | fidl::unowned_ptr_t<int32_t> ptr(&val); | 
|  | fidl::unowned_ptr_t<const int32_t> const_ptr(ptr); | 
|  | EXPECT_EQ(*const_ptr, val); | 
|  | } | 
|  |  | 
|  | TEST(UnownedPtr, Casting) { | 
|  | class Base {}; | 
|  | class Derived : public Base {}; | 
|  | Derived d; | 
|  | fidl::unowned_ptr_t<Derived> d_ptr(&d); | 
|  | EXPECT_EQ(static_cast<fidl::unowned_ptr_t<Base>>(d_ptr).get(), static_cast<Base*>(&d)); | 
|  |  | 
|  | auto vptr = static_cast<fidl::unowned_ptr_t<void>>(d_ptr); | 
|  | EXPECT_EQ(vptr, fidl::unowned_ptr_t<void>(&d)); | 
|  |  | 
|  | auto d_ptr2 = static_cast<fidl::unowned_ptr_t<Derived>>(vptr); | 
|  | EXPECT_EQ(d_ptr2, d_ptr); | 
|  | } |