From 8549d0ae47c3c45a7e6a335dcc7e30e67692dc39 Mon Sep 17 00:00:00 2001 From: Hong Shin Date: Mon, 18 Nov 2024 13:30:38 -0800 Subject: [PATCH] hpb: refactor extension_test.cc into its own file PiperOrigin-RevId: 697739629 --- .../Reflection/FeatureSetDescriptor.g.cs | 17 - hpb_generator/tests/extension_test.cc | 406 ++++++++++++++++++ hpb_generator/tests/test_generated.cc | 387 ----------------- 3 files changed, 406 insertions(+), 404 deletions(-) delete mode 100644 csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs create mode 100644 hpb_generator/tests/extension_test.cc diff --git a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs deleted file mode 100644 index 208ce1fcb6319..0000000000000 --- a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs +++ /dev/null @@ -1,17 +0,0 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file or at -// https://developers.google.com/open-source/licenses/bsd -#endregion - -namespace Google.Protobuf.Reflection; - -internal sealed partial class FeatureSetDescriptor -{ - // Canonical serialized form of the edition defaults, generated by embed_edition_defaults. - private const string DefaultsBase64 = - "ChMYhAciACoMCAEQAhgCIAMoATACChMY5wciACoMCAIQARgBIAIoATABChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH"; -} diff --git a/hpb_generator/tests/extension_test.cc b/hpb_generator/tests/extension_test.cc new file mode 100644 index 0000000000000..b5a3218d18a67 --- /dev/null +++ b/hpb_generator/tests/extension_test.cc @@ -0,0 +1,406 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 Google LLC. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "google/protobuf/hpb/extension.h" + +#include +#include +#include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_extension.upb.proto.h" +#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" +#include "google/protobuf/hpb/requires.h" + +namespace { +using ::hpb::internal::Requires; + +using ::hpb_unittest::protos::container_ext; +using ::hpb_unittest::protos::ContainerExtension; +using ::hpb_unittest::protos::other_ext; +using ::hpb_unittest::protos::TestModel; +using ::hpb_unittest::protos::theme; +using ::hpb_unittest::protos::ThemeExtension; +using ::hpb_unittest::someotherpackage::protos::int32_ext; +using ::hpb_unittest::someotherpackage::protos::int64_ext; + +using ::testing::status::IsOkAndHolds; + +TEST(CppGeneratedCode, HasExtension) { + TestModel model; + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); +} + +TEST(CppGeneratedCode, HasExtensionPtr) { + TestModel model; + EXPECT_EQ(false, ::hpb::HasExtension(model.recursive_child(), theme)); +} + +TEST(CppGeneratedCode, ClearExtensionWithEmptyExtension) { + TestModel model; + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + ::hpb::ClearExtension(&model, theme); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); +} + +TEST(CppGeneratedCode, ClearExtensionWithEmptyExtensionPtr) { + TestModel model; + ::hpb::Ptr recursive_child = model.mutable_recursive_child(); + ::hpb::ClearExtension(recursive_child, theme); + EXPECT_EQ(false, ::hpb::HasExtension(recursive_child, theme)); +} + +TEST(CppGeneratedCode, SetExtensionInt32) { + TestModel model; + EXPECT_EQ(false, hpb::HasExtension(&model, int32_ext)); + int32_t val = 55; + auto x = hpb::SetExtension(&model, int32_ext, val); + EXPECT_EQ(true, hpb::HasExtension(&model, int32_ext)); + EXPECT_THAT(hpb::GetExtension(&model, int32_ext), IsOkAndHolds(val)); +} + +TEST(CppGeneratedCode, SetExtensionInt64) { + TestModel model; + EXPECT_EQ(false, hpb::HasExtension(&model, int64_ext)); + int64_t val = std::numeric_limits::max() + int64_t{1}; + auto x = hpb::SetExtension(&model, int64_ext, val); + EXPECT_EQ(true, hpb::HasExtension(&model, int64_ext)); + EXPECT_THAT(hpb::GetExtension(&model, int64_ext), IsOkAndHolds(val)); +} + +TEST(CppGeneratedCode, SetExtension) { + TestModel model; + void* prior_message; + { + // Use a nested scope to make sure the arenas are fused correctly. + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + prior_message = hpb::interop::upb::GetMessage(&extension1); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, + ::hpb::SetExtension(&model, theme, std::move(extension1)).ok()); + } + EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); + auto ext = hpb::GetExtension(&model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_EQ(hpb::interop::upb::GetMessage(*ext), prior_message); +} + +TEST(CppGeneratedCode, SetExtensionWithPtr) { + ::hpb::Arena arena_model; + ::hpb::Ptr model = ::hpb::CreateMessage(arena_model); + void* prior_message; + { + // Use a nested scope to make sure the arenas are fused correctly. + ::hpb::Arena arena; + ::hpb::Ptr extension1 = + ::hpb::CreateMessage(arena); + extension1->set_ext_name("Hello World"); + prior_message = hpb::interop::upb::GetMessage(extension1); + EXPECT_EQ(false, ::hpb::HasExtension(model, theme)); + auto res = ::hpb::SetExtension(model, theme, extension1); + EXPECT_EQ(true, res.ok()); + } + EXPECT_EQ(true, ::hpb::HasExtension(model, theme)); + auto ext = hpb::GetExtension(model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_NE(hpb::interop::upb::GetMessage(*ext), prior_message); +} + +#ifndef _MSC_VER +TEST(CppGeneratedCode, SetExtensionShouldNotCompileForWrongType) { + ::hpb::Arena arena; + ::hpb::Ptr model = ::hpb::CreateMessage(arena); + ThemeExtension extension1; + ContainerExtension extension2; + + const auto canSetExtension = [&](auto l) { + return Requires(l); + }; + EXPECT_TRUE(canSetExtension( + [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension1)) {})); + // Wrong extension value type should fail to compile. + EXPECT_TRUE(!canSetExtension( + [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension2)) {})); + // Wrong extension id with correct extension type should fail to compile. + EXPECT_TRUE( + !canSetExtension([](auto p) -> decltype(::hpb::SetExtension( + p, container_ext, extension1)) {})); +} +#endif + +TEST(CppGeneratedCode, SetExtensionWithPtrSameArena) { + ::hpb::Arena arena; + ::hpb::Ptr model = ::hpb::CreateMessage(arena); + void* prior_message; + { + // Use a nested scope to make sure the arenas are fused correctly. + ::hpb::Ptr extension1 = + ::hpb::CreateMessage(arena); + extension1->set_ext_name("Hello World"); + prior_message = hpb::interop::upb::GetMessage(extension1); + EXPECT_EQ(false, ::hpb::HasExtension(model, theme)); + auto res = ::hpb::SetExtension(model, theme, extension1); + EXPECT_EQ(true, res.ok()); + } + EXPECT_EQ(true, ::hpb::HasExtension(model, theme)); + auto ext = hpb::GetExtension(model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_NE(hpb::interop::upb::GetMessage(*ext), prior_message); +} + +TEST(CppGeneratedCode, SetExtensionFusingFailureShouldCopy) { + // Use an initial block to disallow fusing. + char initial_block[1000]; + hpb::Arena arena(initial_block, sizeof(initial_block)); + + hpb::Ptr model = ::hpb::CreateMessage(arena); + + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + ASSERT_FALSE( + upb_Arena_Fuse(arena.ptr(), hpb::interop::upb::GetArena(&extension1))); + EXPECT_FALSE(::hpb::HasExtension(model, theme)); + auto status = ::hpb::SetExtension(model, theme, std::move(extension1)); + EXPECT_TRUE(status.ok()); + EXPECT_TRUE(::hpb::HasExtension(model, theme)); + EXPECT_TRUE(hpb::GetExtension(model, theme).ok()); +} + +TEST(CppGeneratedCode, SetExtensionShouldClone) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + extension1.set_ext_name("Goodbye"); + EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); + auto ext = hpb::GetExtension(&model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_EQ((*ext)->ext_name(), "Hello World"); +} + +TEST(CppGeneratedCode, SetExtensionShouldCloneConst) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, + ::hpb::SetExtension(&model, theme, std::as_const(extension1)).ok()); + extension1.set_ext_name("Goodbye"); + EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); + auto ext = hpb::GetExtension(&model, theme); + EXPECT_TRUE(ext.ok()); + EXPECT_EQ((*ext)->ext_name(), "Hello World"); +} + +TEST(CppGeneratedCode, SetExtensionOnMutableChild) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(model.mutable_recursive_child(), theme)); + EXPECT_EQ(true, ::hpb::SetExtension(model.mutable_recursive_child(), theme, + extension1) + .ok()); + EXPECT_EQ(true, ::hpb::HasExtension(model.mutable_recursive_child(), theme)); +} + +TEST(CppGeneratedCode, GetExtension) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + EXPECT_EQ("Hello World", + hpb::GetExtension(&model, theme).value()->ext_name()); +} + +TEST(CppGeneratedCode, GetExtensionInt32WithDefault) { + TestModel model; + auto res = hpb::GetExtension(&model, int32_ext); + EXPECT_TRUE(res.ok()); + EXPECT_EQ(*res, 644); +} + +TEST(CppGeneratedCode, GetExtensionInt64WithDefault) { + TestModel model; + auto res = hpb::GetExtension(&model, int64_ext); + EXPECT_TRUE(res.ok()); + int64_t expected = std::numeric_limits::max() + int64_t{1}; + EXPECT_EQ(*res, expected); +} + +TEST(CppGeneratedCode, GetExtensionOnMutableChild) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + ::hpb::Ptr mutable_recursive_child = + model.mutable_recursive_child(); + EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme)); + EXPECT_EQ( + true, + ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok()); + EXPECT_EQ( + "Hello World", + hpb::GetExtension(mutable_recursive_child, theme).value()->ext_name()); +} + +TEST(CppGeneratedCode, GetExtensionOnImmutableChild) { + TestModel model; + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + ::hpb::Ptr mutable_recursive_child = + model.mutable_recursive_child(); + EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme)); + EXPECT_EQ( + true, + ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok()); + ::hpb::Ptr recursive_child = model.recursive_child(); + EXPECT_EQ("Hello World", + hpb::GetExtension(recursive_child, theme).value()->ext_name()); +} + +TEST(CppGeneratedCode, Parse) { + TestModel model; + model.set_str1("Test123"); + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + TestModel parsed_model = ::hpb::Parse(bytes.value()).value(); + EXPECT_EQ("Test123", parsed_model.str1()); + EXPECT_EQ(true, hpb::GetExtension(&parsed_model, theme).ok()); +} + +TEST(CppGeneratedCode, ParseIntoPtrToModel) { + TestModel model; + model.set_str1("Test123"); + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + ::hpb::Ptr parsed_model = ::hpb::CreateMessage(arena); + EXPECT_TRUE(::hpb::Parse(parsed_model, bytes.value())); + EXPECT_EQ("Test123", parsed_model->str1()); + // Should return an extension even if we don't pass ExtensionRegistry + // by promoting unknown. + EXPECT_EQ(true, hpb::GetExtension(parsed_model, theme).ok()); +} + +TEST(CppGeneratedCode, ParseWithExtensionRegistry) { + TestModel model; + model.set_str1("Test123"); + ThemeExtension extension1; + extension1.set_ext_name("Hello World"); + EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); + EXPECT_EQ(true, ::hpb::SetExtension(&model, ThemeExtension::theme_extension, + extension1) + .ok()); + ::upb::Arena arena; + auto bytes = ::hpb::Serialize(&model, arena); + EXPECT_EQ(true, bytes.ok()); + + TestModel parsed_model = + ::hpb::Parse(bytes.value(), + hpb::ExtensionRegistry::generated_registry()) + .value(); + EXPECT_EQ("Test123", parsed_model.str1()); + EXPECT_EQ(true, hpb::GetExtension(&parsed_model, theme).ok()); + EXPECT_EQ( + true, + hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension).ok()); + EXPECT_EQ("Hello World", + hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension) + .value() + ->ext_name()); +} + +TEST(CppGeneratedCode, ClearSubMessage) { + // Fill model. + TestModel model; + model.set_int64(5); + auto new_child = model.mutable_child_model_1(); + new_child->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); + EXPECT_TRUE(model.mutable_child_model_1()->has_child_str1()); + // Clear using Ptr + ::hpb::ClearMessage(model.mutable_child_model_1()); + EXPECT_FALSE(model.mutable_child_model_1()->has_child_str1()); +} + +TEST(CppGeneratedCode, ClearMessage) { + // Fill model. + TestModel model; + model.set_int64(5); + model.set_str2("Hello"); + auto new_child = model.add_child_models(); + ASSERT_TRUE(new_child.ok()); + new_child.value()->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); + // Clear using T* + ::hpb::ClearMessage(&model); + // Verify that scalars, repeated fields and extensions are cleared. + EXPECT_FALSE(model.has_int64()); + EXPECT_FALSE(model.has_str2()); + EXPECT_TRUE(model.child_models().empty()); + EXPECT_FALSE(::hpb::HasExtension(&model, theme)); +} + +TEST(CppGeneratedCode, DeepCopy) { + // Fill model. + TestModel model; + model.set_int64(5); + model.set_str2("Hello"); + auto new_child = model.add_child_models(); + ASSERT_TRUE(new_child.ok()); + new_child.value()->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); + TestModel target; + target.set_b1(true); + ::hpb::DeepCopy(&model, &target); + EXPECT_FALSE(target.b1()) << "Target was not cleared before copying content "; + EXPECT_EQ(target.str2(), "Hello"); + EXPECT_TRUE(::hpb::HasExtension(&target, theme)); +} + +TEST(CppGeneratedCode, HasExtensionAndRegistry) { + // Fill model. + TestModel source; + source.set_int64(5); + source.set_str2("Hello"); + auto new_child = source.add_child_models(); + ASSERT_TRUE(new_child.ok()); + new_child.value()->set_child_str1("text in child"); + ThemeExtension extension1; + extension1.set_ext_name("name in extension"); + ASSERT_TRUE(::hpb::SetExtension(&source, theme, extension1).ok()); + + // Now that we have a source model with extension data, serialize. + ::hpb::Arena arena; + std::string data = std::string(::hpb::Serialize(&source, arena).value()); + + // Test with ExtensionRegistry + TestModel parsed_model = + ::hpb::Parse(data, + hpb::ExtensionRegistry::generated_registry()) + .value(); + EXPECT_TRUE(::hpb::HasExtension(&parsed_model, theme)); +} + +TEST(CppGeneratedCode, ExtensionFieldNumberConstant) { + EXPECT_EQ(12003, ::hpb::ExtensionNumber(ThemeExtension::theme_extension)); +} + +} // namespace diff --git a/hpb_generator/tests/test_generated.cc b/hpb_generator/tests/test_generated.cc index 497d36b1c3c38..ac370636a76ac 100644 --- a/hpb_generator/tests/test_generated.cc +++ b/hpb_generator/tests/test_generated.cc @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -24,23 +23,17 @@ #include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" #include "google/protobuf/hpb/arena.h" #include "google/protobuf/hpb/backend/upb/interop.h" -#include "google/protobuf/hpb/extension.h" #include "google/protobuf/hpb/hpb.h" #include "google/protobuf/hpb/ptr.h" #include "google/protobuf/hpb/repeated_field.h" #include "google/protobuf/hpb/requires.h" -#include "upb/mem/arena.h" #include "upb/mem/arena.hpp" -#include "upb/mini_table/extension.h" namespace { using ::hpb::internal::Requires; using ::hpb_unittest::protos::Child; using ::hpb_unittest::protos::ChildModel1; -using ::hpb_unittest::protos::container_ext; -using ::hpb_unittest::protos::ContainerExtension; -using ::hpb_unittest::protos::other_ext; using ::hpb_unittest::protos::Parent; using ::hpb_unittest::protos::ParentWithMap; using ::hpb_unittest::protos::ParentWithRepeated; @@ -51,12 +44,7 @@ using ::hpb_unittest::protos::TestModel_Category; using ::hpb_unittest::protos::TestModel_Category_IMAGES; using ::hpb_unittest::protos::TestModel_Category_NEWS; using ::hpb_unittest::protos::TestModel_Category_VIDEO; -using ::hpb_unittest::protos::theme; -using ::hpb_unittest::protos::ThemeExtension; -using ::hpb_unittest::someotherpackage::protos::int32_ext; -using ::hpb_unittest::someotherpackage::protos::int64_ext; using ::testing::ElementsAre; -using ::testing::status::IsOkAndHolds; TEST(CppGeneratedCode, Constructor) { TestModel test_model; } @@ -709,240 +697,6 @@ TEST(CppGeneratedCode, MessageMapStringKeyAndInt32Value) { EXPECT_EQ(false, result_after_delete.ok()); } -TEST(CppGeneratedCode, HasExtension) { - TestModel model; - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); -} - -TEST(CppGeneratedCode, HasExtensionPtr) { - TestModel model; - EXPECT_EQ(false, ::hpb::HasExtension(model.recursive_child(), theme)); -} - -TEST(CppGeneratedCode, ClearExtensionWithEmptyExtension) { - TestModel model; - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); - ::hpb::ClearExtension(&model, theme); - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); -} - -TEST(CppGeneratedCode, ClearExtensionWithEmptyExtensionPtr) { - TestModel model; - ::hpb::Ptr recursive_child = model.mutable_recursive_child(); - ::hpb::ClearExtension(recursive_child, theme); - EXPECT_EQ(false, ::hpb::HasExtension(recursive_child, theme)); -} - -TEST(CppGeneratedCode, SetExtensionInt32) { - TestModel model; - EXPECT_EQ(false, hpb::HasExtension(&model, int32_ext)); - int32_t val = 55; - auto x = hpb::SetExtension(&model, int32_ext, val); - EXPECT_EQ(true, hpb::HasExtension(&model, int32_ext)); - EXPECT_THAT(hpb::GetExtension(&model, int32_ext), IsOkAndHolds(val)); -} - -TEST(CppGeneratedCode, SetExtensionInt64) { - TestModel model; - EXPECT_EQ(false, hpb::HasExtension(&model, int64_ext)); - int64_t val = std::numeric_limits::max() + int64_t{1}; - auto x = hpb::SetExtension(&model, int64_ext, val); - EXPECT_EQ(true, hpb::HasExtension(&model, int64_ext)); - EXPECT_THAT(hpb::GetExtension(&model, int64_ext), IsOkAndHolds(val)); -} - -TEST(CppGeneratedCode, SetExtension) { - TestModel model; - void* prior_message; - { - // Use a nested scope to make sure the arenas are fused correctly. - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - prior_message = hpb::interop::upb::GetMessage(&extension1); - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); - EXPECT_EQ(true, - ::hpb::SetExtension(&model, theme, std::move(extension1)).ok()); - } - EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); - auto ext = hpb::GetExtension(&model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_EQ(hpb::interop::upb::GetMessage(*ext), prior_message); -} - -TEST(CppGeneratedCode, SetExtensionWithPtr) { - ::hpb::Arena arena_model; - ::hpb::Ptr model = ::hpb::CreateMessage(arena_model); - void* prior_message; - { - // Use a nested scope to make sure the arenas are fused correctly. - ::hpb::Arena arena; - ::hpb::Ptr extension1 = - ::hpb::CreateMessage(arena); - extension1->set_ext_name("Hello World"); - prior_message = hpb::interop::upb::GetMessage(extension1); - EXPECT_EQ(false, ::hpb::HasExtension(model, theme)); - auto res = ::hpb::SetExtension(model, theme, extension1); - EXPECT_EQ(true, res.ok()); - } - EXPECT_EQ(true, ::hpb::HasExtension(model, theme)); - auto ext = hpb::GetExtension(model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_NE(hpb::interop::upb::GetMessage(*ext), prior_message); -} - -#ifndef _MSC_VER -TEST(CppGeneratedCode, SetExtensionShouldNotCompileForWrongType) { - ::hpb::Arena arena; - ::hpb::Ptr model = ::hpb::CreateMessage(arena); - ThemeExtension extension1; - ContainerExtension extension2; - - const auto canSetExtension = [&](auto l) { - return Requires(l); - }; - EXPECT_TRUE(canSetExtension( - [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension1)) {})); - // Wrong extension value type should fail to compile. - EXPECT_TRUE(!canSetExtension( - [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension2)) {})); - // Wrong extension id with correct extension type should fail to compile. - EXPECT_TRUE( - !canSetExtension([](auto p) -> decltype(::hpb::SetExtension( - p, container_ext, extension1)) {})); -} -#endif - -TEST(CppGeneratedCode, SetExtensionWithPtrSameArena) { - ::hpb::Arena arena; - ::hpb::Ptr model = ::hpb::CreateMessage(arena); - void* prior_message; - { - // Use a nested scope to make sure the arenas are fused correctly. - ::hpb::Ptr extension1 = - ::hpb::CreateMessage(arena); - extension1->set_ext_name("Hello World"); - prior_message = hpb::interop::upb::GetMessage(extension1); - EXPECT_EQ(false, ::hpb::HasExtension(model, theme)); - auto res = ::hpb::SetExtension(model, theme, extension1); - EXPECT_EQ(true, res.ok()); - } - EXPECT_EQ(true, ::hpb::HasExtension(model, theme)); - auto ext = hpb::GetExtension(model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_NE(hpb::interop::upb::GetMessage(*ext), prior_message); -} - -TEST(CppGeneratedCode, SetExtensionFusingFailureShouldCopy) { - // Use an initial block to disallow fusing. - char initial_block[1000]; - hpb::Arena arena(initial_block, sizeof(initial_block)); - - hpb::Ptr model = ::hpb::CreateMessage(arena); - - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - ASSERT_FALSE( - upb_Arena_Fuse(arena.ptr(), hpb::interop::upb::GetArena(&extension1))); - EXPECT_FALSE(::hpb::HasExtension(model, theme)); - auto status = ::hpb::SetExtension(model, theme, std::move(extension1)); - EXPECT_TRUE(status.ok()); - EXPECT_TRUE(::hpb::HasExtension(model, theme)); - EXPECT_TRUE(hpb::GetExtension(model, theme).ok()); -} - -TEST(CppGeneratedCode, SetExtensionShouldClone) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); - EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); - extension1.set_ext_name("Goodbye"); - EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); - auto ext = hpb::GetExtension(&model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_EQ((*ext)->ext_name(), "Hello World"); -} - -TEST(CppGeneratedCode, SetExtensionShouldCloneConst) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); - EXPECT_EQ(true, - ::hpb::SetExtension(&model, theme, std::as_const(extension1)).ok()); - extension1.set_ext_name("Goodbye"); - EXPECT_EQ(true, ::hpb::HasExtension(&model, theme)); - auto ext = hpb::GetExtension(&model, theme); - EXPECT_TRUE(ext.ok()); - EXPECT_EQ((*ext)->ext_name(), "Hello World"); -} - -TEST(CppGeneratedCode, SetExtensionOnMutableChild) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::hpb::HasExtension(model.mutable_recursive_child(), theme)); - EXPECT_EQ(true, ::hpb::SetExtension(model.mutable_recursive_child(), theme, - extension1) - .ok()); - EXPECT_EQ(true, ::hpb::HasExtension(model.mutable_recursive_child(), theme)); -} - -TEST(CppGeneratedCode, GetExtension) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(false, ::hpb::HasExtension(&model, theme)); - EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); - EXPECT_EQ("Hello World", - hpb::GetExtension(&model, theme).value()->ext_name()); -} - -TEST(CppGeneratedCode, GetExtensionInt32WithDefault) { - TestModel model; - auto res = hpb::GetExtension(&model, int32_ext); - EXPECT_TRUE(res.ok()); - EXPECT_EQ(*res, 644); -} - -TEST(CppGeneratedCode, GetExtensionInt64WithDefault) { - TestModel model; - auto res = hpb::GetExtension(&model, int64_ext); - EXPECT_TRUE(res.ok()); - int64_t expected = std::numeric_limits::max() + int64_t{1}; - EXPECT_EQ(*res, expected); -} - -TEST(CppGeneratedCode, GetExtensionOnMutableChild) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - ::hpb::Ptr mutable_recursive_child = - model.mutable_recursive_child(); - EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme)); - EXPECT_EQ( - true, - ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok()); - EXPECT_EQ( - "Hello World", - hpb::GetExtension(mutable_recursive_child, theme).value()->ext_name()); -} - -TEST(CppGeneratedCode, GetExtensionOnImmutableChild) { - TestModel model; - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - ::hpb::Ptr mutable_recursive_child = - model.mutable_recursive_child(); - EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme)); - EXPECT_EQ( - true, - ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok()); - ::hpb::Ptr recursive_child = model.recursive_child(); - EXPECT_EQ("Hello World", - hpb::GetExtension(recursive_child, theme).value()->ext_name()); -} - TEST(CppGeneratedCode, SerializeUsingArena) { TestModel model; model.set_str1("Hello World"); @@ -976,65 +730,6 @@ TEST(CppGeneratedCode, SerializeNestedMessageUsingArena) { EXPECT_EQ("Hello World", parsed_model.str1()); } -TEST(CppGeneratedCode, Parse) { - TestModel model; - model.set_str1("Test123"); - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); - ::upb::Arena arena; - auto bytes = ::hpb::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - TestModel parsed_model = ::hpb::Parse(bytes.value()).value(); - EXPECT_EQ("Test123", parsed_model.str1()); - EXPECT_EQ(true, hpb::GetExtension(&parsed_model, theme).ok()); -} - -TEST(CppGeneratedCode, ParseIntoPtrToModel) { - TestModel model; - model.set_str1("Test123"); - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); - ::upb::Arena arena; - auto bytes = ::hpb::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - ::hpb::Ptr parsed_model = ::hpb::CreateMessage(arena); - EXPECT_TRUE(::hpb::Parse(parsed_model, bytes.value())); - EXPECT_EQ("Test123", parsed_model->str1()); - // Should return an extension even if we don't pass ExtensionRegistry - // by promoting unknown. - EXPECT_EQ(true, hpb::GetExtension(parsed_model, theme).ok()); -} - -TEST(CppGeneratedCode, ParseWithExtensionRegistry) { - TestModel model; - model.set_str1("Test123"); - ThemeExtension extension1; - extension1.set_ext_name("Hello World"); - EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok()); - EXPECT_EQ(true, ::hpb::SetExtension(&model, ThemeExtension::theme_extension, - extension1) - .ok()); - ::upb::Arena arena; - auto bytes = ::hpb::Serialize(&model, arena); - EXPECT_EQ(true, bytes.ok()); - - TestModel parsed_model = - ::hpb::Parse(bytes.value(), - hpb::ExtensionRegistry::generated_registry()) - .value(); - EXPECT_EQ("Test123", parsed_model.str1()); - EXPECT_EQ(true, hpb::GetExtension(&parsed_model, theme).ok()); - EXPECT_EQ( - true, - hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension).ok()); - EXPECT_EQ("Hello World", - hpb::GetExtension(&parsed_model, ThemeExtension::theme_extension) - .value() - ->ext_name()); -} - TEST(CppGeneratedCode, NameCollisions) { TestModel model; model.set_template_("test"); @@ -1176,41 +871,6 @@ TEST(CppGeneratedCode, PtrImplicitConversion) { EXPECT_EQ(model_ptr->int64(), 5); } -TEST(CppGeneratedCode, ClearSubMessage) { - // Fill model. - TestModel model; - model.set_int64(5); - auto new_child = model.mutable_child_model_1(); - new_child->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); - EXPECT_TRUE(model.mutable_child_model_1()->has_child_str1()); - // Clear using Ptr - ::hpb::ClearMessage(model.mutable_child_model_1()); - EXPECT_FALSE(model.mutable_child_model_1()->has_child_str1()); -} - -TEST(CppGeneratedCode, ClearMessage) { - // Fill model. - TestModel model; - model.set_int64(5); - model.set_str2("Hello"); - auto new_child = model.add_child_models(); - ASSERT_TRUE(new_child.ok()); - new_child.value()->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); - // Clear using T* - ::hpb::ClearMessage(&model); - // Verify that scalars, repeated fields and extensions are cleared. - EXPECT_FALSE(model.has_int64()); - EXPECT_FALSE(model.has_str2()); - EXPECT_TRUE(model.child_models().empty()); - EXPECT_FALSE(::hpb::HasExtension(&model, theme)); -} - TEST(CppGeneratedCode, CanInvokeClearMessageWithPtr) { // Fill model. TestModel model; @@ -1249,58 +909,11 @@ TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstRawPtr) { EXPECT_FALSE(CanCallClearMessage()); } -TEST(CppGeneratedCode, DeepCopy) { - // Fill model. - TestModel model; - model.set_int64(5); - model.set_str2("Hello"); - auto new_child = model.add_child_models(); - ASSERT_TRUE(new_child.ok()); - new_child.value()->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok()); - TestModel target; - target.set_b1(true); - ::hpb::DeepCopy(&model, &target); - EXPECT_FALSE(target.b1()) << "Target was not cleared before copying content "; - EXPECT_EQ(target.str2(), "Hello"); - EXPECT_TRUE(::hpb::HasExtension(&target, theme)); -} - -TEST(CppGeneratedCode, HasExtensionAndRegistry) { - // Fill model. - TestModel source; - source.set_int64(5); - source.set_str2("Hello"); - auto new_child = source.add_child_models(); - ASSERT_TRUE(new_child.ok()); - new_child.value()->set_child_str1("text in child"); - ThemeExtension extension1; - extension1.set_ext_name("name in extension"); - ASSERT_TRUE(::hpb::SetExtension(&source, theme, extension1).ok()); - - // Now that we have a source model with extension data, serialize. - ::hpb::Arena arena; - std::string data = std::string(::hpb::Serialize(&source, arena).value()); - - // Test with ExtensionRegistry - TestModel parsed_model = - ::hpb::Parse(data, - hpb::ExtensionRegistry::generated_registry()) - .value(); - EXPECT_TRUE(::hpb::HasExtension(&parsed_model, theme)); -} - TEST(CppGeneratedCode, FieldNumberConstants) { static_assert(TestModel::kChildMapFieldNumber == 225); EXPECT_EQ(225, TestModel::kChildMapFieldNumber); } -TEST(CppGeneratedCode, ExtensionFieldNumberConstant) { - EXPECT_EQ(12003, ::hpb::ExtensionNumber(ThemeExtension::theme_extension)); -} - TEST(CppGeneratedCode, ClearConstMessageShouldFailForConstChild) { TestModel model; EXPECT_FALSE(CanCallClearMessage());