1// 2// Copyright 2025 The ANGLE Project Authors. All rights reserved. 3// of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6// ObjCPtr_test.cpp: 7// Test for functionality in ObjCPtr.h 8 9#import "common/apple/ObjCPtr.h" 10#import <Metal/Metal.h> 11#import "gtest/gtest.h" 12 13namespace 14{ 15using namespace angle; 16 17// This explains why the implementation has ObjCPtr<U> &&other constructor/operator= 18// as opposed to ObjCPtr &&other ones. 19TEST(ObjCPtrTest, ImplementationDetailExplanation) 20{ 21 // For Obj-C interfaces we would like the client to use ObjCPtr<T> form, similar 22 // to any C++ smart pointer. 23 MTLStencilDescriptor *rawDesc = nil; 24 ObjCPtr<MTLStencilDescriptor> stencilDesc = adoptObjCPtr(rawDesc); 25 26 // For Obj-C protocols we would like the client to use ObjCPtr<id<P>> form, 27 // which resembles the normal smart pointer form textually: 28 id<MTLDevice> rawDevice = nil; 29 ObjCPtr<id<MTLDevice>> device = adoptObjCPtr(rawDevice); 30 31 // adoptObjCPtr for Obj-C interface types works as expected: 32 { 33 auto result = adoptObjCPtr(rawDesc); 34 static_assert(std::is_same_v<ObjCPtr<MTLStencilDescriptor>, decltype(result)>); 35 } 36 37 // adoptObjCPtr for protocols does not: 38 { 39 auto result = adoptObjCPtr(rawDevice); 40 static_assert(!std::is_same_v<ObjCPtr<id<MTLDevice>>, decltype(result)>); 41 static_assert( 42 std::is_same_v<ObjCPtr<std::remove_pointer_t<id<MTLDevice>>>, decltype(result)>); 43 } 44} 45 46TEST(ObjCPtrTest, Comparison) 47{ 48 ObjCPtr<MTLStencilDescriptor> a = adoptObjCPtr([[MTLStencilDescriptor alloc] init]); 49 ObjCPtr<MTLStencilDescriptor> b; 50 EXPECT_TRUE(a == a); 51 EXPECT_TRUE(a != b); 52 EXPECT_TRUE(a != nullptr); 53 EXPECT_TRUE(b == nullptr); 54 EXPECT_TRUE(nullptr != a); 55 EXPECT_TRUE(nullptr == b); 56 EXPECT_TRUE(a != nil); 57 EXPECT_TRUE(b == nil); 58 EXPECT_TRUE(nil != a); 59 EXPECT_TRUE(nil == b); 60 EXPECT_TRUE(!!a); 61 EXPECT_TRUE(!b); 62} 63 64TEST(ObjCPtrTest, Copy) 65{ 66 ObjCPtr<MTLStencilDescriptor> a = adoptObjCPtr([[MTLStencilDescriptor alloc] init]); 67 ObjCPtr<MTLStencilDescriptor> b = a; 68 EXPECT_EQ(a, b); 69 EXPECT_NE(a, nullptr); 70 a = {}; 71 EXPECT_NE(a, b); 72} 73 74TEST(ObjCPtrTest, LeakObject) 75{ 76 ObjCPtr<MTLStencilDescriptor> a = adoptObjCPtr([[MTLStencilDescriptor alloc] init]); 77 EXPECT_NE(a, nullptr); 78 auto rawA = a.leakObject(); 79 EXPECT_EQ(a, nullptr); 80 EXPECT_EQ(a.leakObject(), nullptr); 81 a = adoptObjCPtr(rawA); 82} 83 84TEST(ObjCPtrTest, SelfAssignment) 85{ 86 ObjCPtr a = adoptObjCPtr([[MTLStencilDescriptor alloc] init]); 87 auto rawA = a.get(); 88 auto &r = a; 89 a = r; 90 EXPECT_EQ(a, rawA); 91 a = std::move(r); 92 EXPECT_EQ(a, rawA); 93} 94 95} // namespace 96