/* * 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 #include #include #include #include #include namespace mp11 = boost::mp11; using apache::thrift::protocol::asValueStruct; using apache::thrift::test::testset::FieldModifier; namespace apache::thrift::conformance::data { namespace { template Test createRoundTripTest( const AnyRegistry& registry, const Protocol& protocol) { using namespace apache::thrift::test::testset::detail; const std::string& typeName = getTestTypeName(); Test test; test.name() = protocol.name(); test.tags()->emplace("idl/"); for (const auto& value : ValueGenerator::getInterestingValues()) { RoundTripTestCase roundTrip; // asValueStruct doesn't work with adapted values if constexpr (!is_adapted) { // Test case #1: Use ValueStruct roundTrip.request()->value() = registry.store(asValueStruct(value.value), protocol); auto& testCase = test.testCases()->emplace_back(); testCase.name() = fmt::format("{}/{}", typeName, value.name); testCase.test()->roundTrip_ref() = roundTrip; } auto addTestCase = [&](auto data, auto msg) { roundTrip.request()->value() = registry.store(data, protocol); auto& testCase = test.testCases()->emplace_back(); testCase.name() = msg; testCase.test()->roundTrip_ref() = roundTrip; }; auto addStruct = [&](auto modSet, auto msg) { using ModSet = decltype(modSet); typename struct_ByFieldType::type data; if constexpr ( std::is_same_v, ModSet> || std::is_same_v, ModSet>) { data.field_1().ensure().value = type::native_type{value.value}; } else { data.field_1() = type::native_type{value.value}; } addTestCase( data, fmt::format("testset.{}{}/{}", msg, typeName, value.name)); }; // Test case #2: Unqualified field addStruct(mod_set<>{}, ""); typename union_ByFieldType>::type unionData; unionData.field_1_ref() = type::native_type{value.value}; addTestCase( unionData, fmt::format("testset.union.{}/{}", typeName, value.name)); // these aren't tested with adapter if constexpr (!is_adapted) { // Test case #3: Optional field addStruct(mod_set{}, "Optional."); addTestCase( typename struct_ByFieldType< ElementTag, mod_set>::type{}, fmt::format("testset.Optional.{}/empty_optional", typeName)); // Test case #4: Terse field addStruct(mod_set{}, "Terse."); } // Test case #5: Adapted field addStruct(mod_set{}, "Adapted."); // Test case #6: Adapted field with a Field Adapter addStruct(mod_set{}, "FieldAdapted."); } return test; } template using TypeAdapter = type::adapted<::apache::thrift::test::TemplatedTestAdapter, Tag>; void addRoundTripToSuite( const AnyRegistry& registry, const Protocol& protocol, TestSuite& suite) { mp11::mp_for_each([&](auto element_tag) { using ElementTag = decltype(element_tag); suite.tests()->emplace_back( createRoundTripTest(registry, protocol)); suite.tests()->emplace_back( createRoundTripTest, true>(registry, protocol)); if constexpr (!std::is_same_v) { suite.tests()->emplace_back( createRoundTripTest, false>( registry, protocol)); suite.tests()->emplace_back( createRoundTripTest>, true>( registry, protocol)); } mp11::mp_for_each([&](auto key_tag) { using KeyTag = decltype(key_tag); suite.tests()->emplace_back( createRoundTripTest, false>( registry, protocol)); suite.tests()->emplace_back( createRoundTripTest< type::map, TypeAdapter>, true>(registry, protocol)); }); }); mp11::mp_for_each([&](auto key_tag) { using KeyTag = decltype(key_tag); suite.tests()->emplace_back( createRoundTripTest, false>(registry, protocol)); suite.tests()->emplace_back( createRoundTripTest>, true>( registry, protocol)); }); } } // namespace TestSuite createRoundTripSuite( const std::set& protocols, const AnyRegistry& registry) { TestSuite suite; suite.name() = "RoundTripTest"; for (const auto& protocol : protocols) { addRoundTripToSuite(registry, protocol, suite); } return suite; } } // namespace apache::thrift::conformance::data