/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * 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 * * http://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 #include #include #include #include namespace apache::thrift::test { // Tests copy with the given src and dst by incrementing the src field. // Assumes src field has a value. // srcFieldRef has field_ref type while src can be other // types like field_ref. template void copyFieldRef(SrcRef srcFieldRef, Src src, Dst dst) { srcFieldRef = can_throw(*srcFieldRef) + 1; op::copy(src, dst); EXPECT_EQ(*dst, *srcFieldRef); } // srcPtr has smart_ptr& type while src can be other // types like const smart_ptr&&. template void copyUniquePointer(SrcPtr& srcPtr, Src&& src, Dst&& dst) { assert(srcPtr != nullptr); *srcPtr = *srcPtr + 1; op::copy(std::forward(src), std::forward(dst)); EXPECT_EQ(*dst, *srcPtr); } template void copySharedPointer(Src&& src, Dst&& dst) { dst = nullptr; op::copy(std::forward(src), std::forward(dst)); EXPECT_EQ(src, dst); } template void testFieldRef(Src src, Dst dst, Ord ord) { using Struct = decltype(src); auto srcField = op::get(src); auto dstField = op::get(dst); // test src = field_ref copyFieldRef(srcField, srcField, dstField); // test src = field_ref const auto& srcConstRef = src; auto srcConstField = op::get(srcConstRef); copyFieldRef(srcField, srcConstField, dstField); // test src = field_ref auto&& srcRvalueRef = std::move(src); auto srcRvalueField = op::get( std::forward(srcRvalueRef)); copyFieldRef(srcField, srcRvalueField, dstField); // test src = field_ref const auto&& srcRvalueConstRef = std::move(src); auto srcRvalueConstField = op::get( std::forward(srcRvalueConstRef)); copyFieldRef(srcField, srcRvalueConstField, dstField); } template void testCopyNotOptional(Src src, Dst dst, Ord ord) { using Struct = decltype(src); auto srcField = op::get(src); auto dstField = op::get(dst); op::copy(srcField, dstField); EXPECT_EQ(*dstField, 0); testFieldRef(src, dst, ord); } template void testCopyOptional(Src src, Dst dst, Ord ord) { using Struct = decltype(src); auto srcField = op::get(src); auto dstField = op::get(dst); // src doesn't have value. op::copy(srcField, dstField); EXPECT_FALSE(dstField.has_value()); dstField = 0; op::copy(srcField, dstField); EXPECT_FALSE(dstField.has_value()); // src has value. srcField = 1; testFieldRef(src, dst, ord); } template void testCopyUniquePointer(Src src, Dst dst, Ord ord) { using Struct = decltype(src); using FieldTag = op::get_field_tag; auto& srcField = op::get(src); auto& dstField = op::get(dst); // src doesn't have value. op::copy(srcField, dstField); EXPECT_EQ(dstField, nullptr); op::ensure(dstField, dst); op::copy(srcField, dstField); EXPECT_EQ(dstField, nullptr); // src has value. op::ensure(srcField, src); copyUniquePointer(srcField, srcField, dstField); copyUniquePointer(srcField, srcField, dstField); // src is const unique_ptr& const auto& srcConstField = srcField; copyUniquePointer(srcField, srcConstField, dstField); // src is unique_ptr&& auto&& srcRvalueField = std::move(srcField); copyUniquePointer( srcField, std::forward(srcRvalueField), dstField); // src is const unique_ptr&& const auto&& srcRvalueConstField = std::move(srcField); copyUniquePointer( srcField, std::forward(srcRvalueConstField), dstField); } template void testCopySharedPointer(Src src, Dst dst, Ord ord) { using Struct = decltype(src); using FieldTag = op::get_field_tag; auto& srcField = op::get(src); auto& dstField = op::get(dst); // src doesn't have value. op::copy(srcField, dstField); EXPECT_EQ(dstField, nullptr); op::ensure(dstField, dst); op::copy(srcField, dstField); EXPECT_EQ(dstField, nullptr); // src has value. op::ensure(srcField, src); copySharedPointer(srcField, dstField); // src is const shared_ptr& const auto& srcConstField = srcField; copySharedPointer(srcConstField, dstField); // src is shared_ptr&& auto&& srcRvalueField = std::move(srcField); copySharedPointer( std::forward(srcRvalueField), dstField); // src is const shared_ptr&& const auto&& srcRvalueConstField = std::move(srcField); copySharedPointer( std::forward(srcRvalueConstField), dstField); } TEST(CopyTest, FieldRefCopyNotOptional) { FieldRefNotOptionalStruct src, dst; op::for_each_ordinal([&](auto fieldOrdinalTag) { testCopyNotOptional(src, dst, fieldOrdinalTag); }); } TEST(CopyTest, FieldRefCopyOptional) { FieldRefOptionalStruct src, dst; op::for_each_ordinal([&](auto fieldOrdinalTag) { testCopyOptional(src, dst, fieldOrdinalTag); }); } TEST(CopyTest, UniquePointer) { UniquePointerStruct src, dst; op::for_each_ordinal([&](auto fieldOrdinalTag) { testCopyUniquePointer(src, dst, fieldOrdinalTag); }); } TEST(CopyTest, SharedPointer) { SharedPointerStruct src, dst; op::for_each_ordinal([&](auto fieldOrdinalTag) { testCopySharedPointer(src, dst, fieldOrdinalTag); }); } TEST(CopyTest, Optional) { std::optional src, dst; op::copy(src, dst); EXPECT_FALSE(bool(dst)); src = 1; op::copy(src, dst); EXPECT_EQ(dst.value(), 1); // test src is const reference const std::optional& srcConst = src; src = 2; op::copy(srcConst, dst); EXPECT_EQ(dst.value(), 2); } } // namespace apache::thrift::test