diff options
Diffstat (limited to 'absl/base/nullability_test.cc')
-rw-r--r-- | absl/base/nullability_test.cc | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/absl/base/nullability_test.cc b/absl/base/nullability_test.cc new file mode 100644 index 00000000..6edd7cd1 --- /dev/null +++ b/absl/base/nullability_test.cc @@ -0,0 +1,129 @@ +// Copyright 2023 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/nullability.h" + +#include <cassert> +#include <memory> +#include <utility> + +#include "gtest/gtest.h" +#include "absl/base/attributes.h" + +namespace { +using ::absl::NonNull; +using ::absl::NullabilityUnknown; +using ::absl::Nullable; + +void funcWithNonnullArg(NonNull<int*> /*arg*/) {} +template <typename T> +void funcWithDeducedNonnullArg(NonNull<T*> /*arg*/) {} + +TEST(NonNullTest, NonNullArgument) { + int var = 0; + funcWithNonnullArg(&var); + funcWithDeducedNonnullArg(&var); +} + +NonNull<int*> funcWithNonnullReturn() { + static int var = 0; + return &var; +} + +TEST(NonNullTest, NonNullReturn) { + auto var = funcWithNonnullReturn(); + (void)var; +} + +TEST(PassThroughTest, PassesThroughRawPointerToInt) { + EXPECT_TRUE((std::is_same<NonNull<int*>, int*>::value)); + EXPECT_TRUE((std::is_same<Nullable<int*>, int*>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<int*>, int*>::value)); +} + +TEST(PassThroughTest, PassesThroughRawPointerToVoid) { + EXPECT_TRUE((std::is_same<NonNull<void*>, void*>::value)); + EXPECT_TRUE((std::is_same<Nullable<void*>, void*>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<void*>, void*>::value)); +} + +TEST(PassThroughTest, PassesThroughUniquePointerToInt) { + using T = std::unique_ptr<int>; + EXPECT_TRUE((std::is_same<NonNull<T>, T>::value)); + EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); +} + +TEST(PassThroughTest, PassesThroughSharedPointerToInt) { + using T = std::shared_ptr<int>; + EXPECT_TRUE((std::is_same<NonNull<T>, T>::value)); + EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); +} + +TEST(PassThroughTest, PassesThroughSharedPointerToVoid) { + using T = std::shared_ptr<void>; + EXPECT_TRUE((std::is_same<NonNull<T>, T>::value)); + EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); +} + +TEST(PassThroughTest, PassesThroughPointerToMemberObject) { + using T = decltype(&std::pair<int, int>::first); + EXPECT_TRUE((std::is_same<NonNull<T>, T>::value)); + EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); +} + +TEST(PassThroughTest, PassesThroughPointerToMemberFunction) { + using T = decltype(&std::unique_ptr<int>::reset); + EXPECT_TRUE((std::is_same<NonNull<T>, T>::value)); + EXPECT_TRUE((std::is_same<Nullable<T>, T>::value)); + EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value)); +} + +} // namespace + +// Nullable ADL lookup test +namespace util { +// Helper for NullableAdlTest. Returns true, denoting that argument-dependent +// lookup found this implementation of DidAdlWin. Must be in namespace +// util itself, not a nested anonymous namespace. +template <typename T> +bool DidAdlWin(T*) { + return true; +} + +// Because this type is defined in namespace util, an unqualified call to +// DidAdlWin with a pointer to MakeAdlWin will find the above implementation. +struct MakeAdlWin {}; +} // namespace util + +namespace { +// Returns false, denoting that ADL did not inspect namespace util. If it +// had, the better match (T*) above would have won out over the (...) here. +bool DidAdlWin(...) { return false; } + +TEST(NullableAdlTest, NullableAddsNothingToArgumentDependentLookup) { + // Treatment: util::Nullable<int*> contributes nothing to ADL because + // int* itself doesn't. + EXPECT_FALSE(DidAdlWin((int*)nullptr)); + EXPECT_FALSE(DidAdlWin((Nullable<int*>)nullptr)); + + // Control: Argument-dependent lookup does find the implementation in + // namespace util when the underlying pointee type resides there. + EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr)); + EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr)); +} +} // namespace |