From 7dcae81096e7543890d92978f2263664bd0e9ade Mon Sep 17 00:00:00 2001
From: Protobuf Team Bot <protobuf-github-bot@google.com>
Date: Thu, 6 Jun 2024 15:40:11 -0700
Subject: [PATCH] Add serialization test and parameterize tests to verify
 behavior in multiple versions of the protocol buffer language.

New serialization test will verify the amount of bytes it takes to serialize a message with a field of type INT32 set to different values.

PiperOrigin-RevId: 641044189
---
 rust/test/BUILD                        |  16 +++
 rust/test/shared/BUILD                 |  12 ++
 rust/test/shared/serialization_test.rs | 182 ++++++++++++++++---------
 3 files changed, 144 insertions(+), 66 deletions(-)

diff --git a/rust/test/BUILD b/rust/test/BUILD
index f7d0d0aa21..aa673aa048 100644
--- a/rust/test/BUILD
+++ b/rust/test/BUILD
@@ -10,6 +10,8 @@ UNITTEST_PROTO3_TARGET = "//src/google/protobuf:test_protos"
 
 UNITTEST_PROTO3_OPTIONAL_TARGET = "//src/google/protobuf:test_protos"
 
+UNITTEST_EDITION_TARGET = "//src/google/protobuf:test_protos"
+
 rust_upb_proto_library(
     name = "unittest_upb_rust_proto",
     testonly = True,
@@ -55,6 +57,20 @@ rust_upb_proto_library(
     deps = [UNITTEST_PROTO3_OPTIONAL_TARGET],
 )
 
+rust_cc_proto_library(
+    name = "unittest_edition_cpp_rust_proto",
+    testonly = True,
+    visibility = ["//rust/test/shared:__subpackages__"],
+    deps = [UNITTEST_EDITION_TARGET],
+)
+
+rust_upb_proto_library(
+    name = "unittest_edition_upb_rust_proto",
+    testonly = True,
+    visibility = ["//rust/test/shared:__subpackages__"],
+    deps = [UNITTEST_EDITION_TARGET],
+)
+
 proto_library(
     name = "parent_proto",
     srcs = ["parent.proto"],
diff --git a/rust/test/shared/BUILD b/rust/test/shared/BUILD
index bdc441caaf..96f589be6f 100644
--- a/rust/test/shared/BUILD
+++ b/rust/test/shared/BUILD
@@ -227,7 +227,13 @@ rust_test(
 rust_test(
     name = "serialization_upb_test",
     srcs = ["serialization_test.rs"],
+    proc_macro_deps = [
+        "@crate_index//:paste",
+    ],
     deps = [
+        "//rust/test:unittest_edition_upb_rust_proto",
+        "//rust/test:unittest_proto3_optional_upb_rust_proto",
+        "//rust/test:unittest_proto3_upb_rust_proto",
         "//rust/test:unittest_upb_rust_proto",
         "@crate_index//:googletest",
     ],
@@ -236,8 +242,14 @@ rust_test(
 rust_test(
     name = "serialization_cpp_test",
     srcs = ["serialization_test.rs"],
+    proc_macro_deps = [
+        "@crate_index//:paste",
+    ],
     deps = [
         "//rust/test:unittest_cpp_rust_proto",
+        "//rust/test:unittest_edition_upb_rust_proto",
+        "//rust/test:unittest_proto3_cpp_rust_proto",
+        "//rust/test:unittest_proto3_optional_cpp_rust_proto",
         "@crate_index//:googletest",
     ],
 )
diff --git a/rust/test/shared/serialization_test.rs b/rust/test/shared/serialization_test.rs
index 4acd57ea57..ab9dd21ca1 100644
--- a/rust/test/shared/serialization_test.rs
+++ b/rust/test/shared/serialization_test.rs
@@ -6,69 +6,119 @@
 // https://developers.google.com/open-source/licenses/bsd
 
 use googletest::prelude::*;
-use unittest_rust_proto::TestAllTypes;
-
-#[test]
-fn serialize_zero_length() {
-    let mut msg = TestAllTypes::new();
-
-    let serialized = msg.serialize().unwrap();
-    assert_that!(serialized.len(), eq(0));
-
-    let serialized = msg.as_view().serialize().unwrap();
-    assert_that!(serialized.len(), eq(0));
-
-    let serialized = msg.as_mut().serialize().unwrap();
-    assert_that!(serialized.len(), eq(0));
-}
-
-#[test]
-fn serialize_deserialize_message() {
-    let mut msg = TestAllTypes::new();
-    msg.set_optional_int64(42);
-    msg.set_optional_bool(true);
-    msg.set_optional_bytes(b"serialize deserialize test");
-
-    let serialized = msg.serialize().unwrap();
-
-    let msg2 = TestAllTypes::parse(&serialized).unwrap();
-    assert_that!(msg.optional_int64(), eq(msg2.optional_int64()));
-    assert_that!(msg.optional_bool(), eq(msg2.optional_bool()));
-    assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes()));
-}
-
-#[test]
-fn deserialize_empty() {
-    assert!(TestAllTypes::parse(&[]).is_ok());
-}
-
-#[test]
-fn deserialize_error() {
-    assert!(TestAllTypes::parse(b"not a serialized proto").is_err());
-}
-
-#[test]
-fn set_bytes_with_serialized_data() {
-    let mut msg = TestAllTypes::new();
-    msg.set_optional_int64(42);
-    msg.set_optional_bool(true);
-    let mut msg2 = TestAllTypes::new();
-    msg2.set_optional_bytes(msg.serialize().unwrap());
-    assert_that!(msg2.optional_bytes(), eq(msg.serialize().unwrap().as_ref()));
-}
-
-#[test]
-fn deserialize_on_previously_allocated_message() {
-    let mut msg = TestAllTypes::new();
-    msg.set_optional_int64(42);
-    msg.set_optional_bool(true);
-    msg.set_optional_bytes(b"serialize deserialize test");
-
-    let serialized = msg.serialize().unwrap();
-
-    let mut msg2 = Box::new(TestAllTypes::new());
-    assert!(msg2.clear_and_parse(&serialized).is_ok());
-    assert_that!(msg.optional_int64(), eq(msg2.optional_int64()));
-    assert_that!(msg.optional_bool(), eq(msg2.optional_bool()));
-    assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes()));
-}
+use paste::paste;
+use unittest_edition_rust_proto::TestAllTypes as TestAllTypesEditions;
+use unittest_proto3_optional_rust_proto::TestProto3Optional;
+use unittest_proto3_rust_proto::TestAllTypes as TestAllTypesProto3;
+use unittest_rust_proto::TestAllTypes as TestAllTypesProto2;
+
+macro_rules! generate_parameterized_serialization_test {
+    ($(($type: ident, $name_ext: ident)),*) => {
+        paste! { $(
+            #[test]
+            fn [< serialization_zero_length_ $name_ext >]() {
+                let mut msg = [< $type >]::new();
+
+                let serialized = msg.serialize().unwrap();
+                assert_that!(serialized.len(), eq(0));
+
+                let serialized = msg.as_view().serialize().unwrap();
+                assert_that!(serialized.len(), eq(0));
+
+                let serialized = msg.as_mut().serialize().unwrap();
+                assert_that!(serialized.len(), eq(0));
+            }
+
+            #[test]
+            fn [< serialize_deserialize_message_ $name_ext>]() {
+                let mut msg = [< $type >]::new();
+                msg.set_optional_int64(42);
+                msg.set_optional_bool(true);
+                msg.set_optional_bytes(b"serialize deserialize test");
+
+                let serialized = msg.serialize().unwrap();
+
+                let msg2 = [< $type >]::parse(&serialized).unwrap();
+                assert_that!(msg.optional_int64(), eq(msg2.optional_int64()));
+                assert_that!(msg.optional_bool(), eq(msg2.optional_bool()));
+                assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes()));
+            }
+
+            #[test]
+            fn [< deserialize_empty_ $name_ext>]() {
+                assert!([< $type >]::parse(&[]).is_ok());
+            }
+
+            #[test]
+            fn [< deserialize_error_ $name_ext>]() {
+                assert!([< $type >]::parse(b"not a serialized proto").is_err());
+            }
+
+            #[test]
+            fn [< set_bytes_with_serialized_data_ $name_ext>]() {
+                let mut msg = [< $type >]::new();
+                msg.set_optional_int64(42);
+                msg.set_optional_bool(true);
+                let mut msg2 = [< $type >]::new();
+                msg2.set_optional_bytes(msg.serialize().unwrap());
+                assert_that!(msg2.optional_bytes(), eq(msg.serialize().unwrap().as_ref()));
+            }
+
+            #[test]
+            fn [< deserialize_on_previously_allocated_message_ $name_ext>]() {
+                let mut msg = [< $type >]::new();
+                msg.set_optional_int64(42);
+                msg.set_optional_bool(true);
+                msg.set_optional_bytes(b"serialize deserialize test");
+
+                let serialized = msg.serialize().unwrap();
+
+                let mut msg2 = Box::new([< $type >]::new());
+                assert!(msg2.clear_and_parse(&serialized).is_ok());
+                assert_that!(msg.optional_int64(), eq(msg2.optional_int64()));
+                assert_that!(msg.optional_bool(), eq(msg2.optional_bool()));
+                assert_that!(msg.optional_bytes(), eq(msg2.optional_bytes()));
+            }
+
+        )* }
+    };
+  }
+
+generate_parameterized_serialization_test!(
+    (TestAllTypesProto2, proto2),
+    (TestAllTypesProto3, proto3),
+    (TestAllTypesEditions, editions),
+    (TestProto3Optional, proto3_optional)
+);
+
+macro_rules! generate_parameterized_int32_byte_size_test {
+    ($(($type: ident, $name_ext: ident)),*) => {
+        paste! { $(
+
+            #[test]
+            fn [< test_int32_byte_size_ $name_ext>]() {
+                let args = vec![(0, 1), (127, 1), (128, 2), (-1, 10)];
+                for arg in args {
+                    let value = arg.0;
+                    let expected_value_size = arg.1;
+                    let mut msg = [< $type >]::new();
+                    // tag for optional_int32 only takes 1 byte
+                    msg.set_optional_int32(value);
+                    let serialized = msg.serialize().unwrap();
+                    // 1 byte for tag and n from expected_value_size
+                    assert_that!(serialized.len(), eq(expected_value_size + 1), "Test failed. Value: {value}. Expected_value_size: {expected_value_size}.");
+                }
+
+            }
+        )* }
+    };
+  }
+
+generate_parameterized_int32_byte_size_test!(
+    (TestAllTypesProto2, proto2),
+    (TestProto3Optional, proto3_optional), /* Test would fail if we were to use
+                                            * TestAllTypesProto3: optional_int32 follows "no
+                                            * presence" semantics and setting it to 0 (default
+                                            * value) will cause it to not be serialized */
+    (TestAllTypesEditions, editions)
+);