| // Copyright 2025 The Abseil Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "absl/base/internal/nullability_traits.h" |
| |
| #include <memory> |
| #include <type_traits> |
| |
| #include "gtest/gtest.h" |
| #include "absl/base/config.h" |
| #include "absl/base/nullability.h" |
| |
| namespace absl { |
| ABSL_NAMESPACE_BEGIN |
| namespace base_internal { |
| namespace { |
| |
| struct NotSmartPtr { |
| int* x; |
| }; |
| |
| class ABSL_NULLABILITY_COMPATIBLE MySmartPtr : std::unique_ptr<int> {}; |
| |
| // The IsNullabilityCompatibleType trait value can only be true when we define |
| // `absl_nullable` (isn't a no-op). |
| #if defined(__clang__) && !defined(__OBJC__) && \ |
| ABSL_HAVE_FEATURE(nullability_on_classes) |
| #define EXPECT_TRUE_IF_SUPPORTED EXPECT_TRUE |
| #else |
| #define EXPECT_TRUE_IF_SUPPORTED EXPECT_FALSE |
| #endif |
| |
| TEST(NullabilityTraitsTest, IsNullabilityEligibleTypePrimitives) { |
| EXPECT_FALSE(IsNullabilityCompatibleType<int>::value); |
| EXPECT_FALSE(IsNullabilityCompatibleType<int*&>::value); |
| |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<int*>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<int**>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<int* const>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<const int*>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<void (*)(int)>::value); |
| } |
| |
| TEST(NullabilityTraitsTest, IsNullabilityCompatibleTypeAliases) { |
| using MyInt = int; |
| using MyIntPtr = int*; |
| EXPECT_FALSE(IsNullabilityCompatibleType<MyInt>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<MyIntPtr>::value); |
| } |
| |
| TEST(NullabilityTraitsTest, IsNullabilityCompatibleTypeSmartPointers) { |
| EXPECT_TRUE_IF_SUPPORTED( |
| IsNullabilityCompatibleType<std::unique_ptr<int>>::value); |
| EXPECT_TRUE_IF_SUPPORTED( |
| IsNullabilityCompatibleType<std::shared_ptr<int>>::value); |
| |
| EXPECT_FALSE(IsNullabilityCompatibleType<NotSmartPtr>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<NotSmartPtr*>::value); |
| EXPECT_TRUE_IF_SUPPORTED(IsNullabilityCompatibleType<MySmartPtr>::value); |
| } |
| |
| #undef EXPECT_TRUE_IF_SUPPORTED |
| |
| TEST(NullabilityTraitsTest, AddNonnullIfCompatiblePassThroughPrimitives) { |
| EXPECT_TRUE((std::is_same_v<AddNonnullIfCompatible<int>::type, int>)); |
| EXPECT_TRUE((std::is_same_v<AddNonnullIfCompatible<int*>::type, int*>)); |
| EXPECT_TRUE( |
| (std::is_same_v<AddNonnullIfCompatible<int* const>::type, int* const>)); |
| } |
| |
| TEST(NullabilityTraitsTest, AddNonnullIfCompatiblePassThroughSmartPointers) { |
| EXPECT_TRUE( |
| (std::is_same_v<AddNonnullIfCompatible<std::unique_ptr<int>>::type, |
| std::unique_ptr<int>>)); |
| EXPECT_TRUE( |
| (std::is_same_v<AddNonnullIfCompatible<std::shared_ptr<int>>::type, |
| std::shared_ptr<int>>)); |
| EXPECT_TRUE( |
| (std::is_same_v<AddNonnullIfCompatible<NotSmartPtr>::type, NotSmartPtr>)); |
| EXPECT_TRUE( |
| (std::is_same_v<AddNonnullIfCompatible<MySmartPtr>::type, MySmartPtr>)); |
| } |
| |
| } // namespace |
| } // namespace base_internal |
| ABSL_NAMESPACE_END |
| } // namespace absl |