Enable rust/test/cpp/interop/... tests on GHA

PiperOrigin-RevId: 681051606
pull/18515/head
Protobuf Team Bot 2 months ago committed by Copybara-Service
parent 9bcd7087ae
commit 6ae5db635e
  1. 3
      .github/workflows/test_rust.yml
  2. 4
      rust/defs.bzl
  3. 24
      rust/test/cpp/interop/BUILD
  4. 16
      rust/test/cpp/interop/interop_test.proto
  5. 94
      rust/test/cpp/interop/main.rs
  6. 38
      rust/test/cpp/interop/test_utils.cc

@ -28,8 +28,9 @@ jobs:
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: rust_linux
bazel: >-
test --cxxopt=-std=c++17 --host_cxxopt=-std=c++17
test --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 --@rules_rust//rust/settings:experimental_use_cc_common_link=True
//rust:all
//rust/test/cpp/interop/...
//rust/test/rust_proto_library_unit_test:rust_upb_aspect_test
//src/google/protobuf/compiler/rust/...
- name: Run Cargo tests

@ -101,8 +101,8 @@ def _rust_proto_library_impl(ctx):
# These two fields present on the dir(crate_info) but break on some versions of Bazel when
# passed back in to crate_info. Strip them for now.
fields.pop("to_json")
fields.pop("to_proto")
fields.pop("to_json", None)
fields.pop("to_proto", None)
crate_info_with_rust_proto_name = rust_common.crate_info(**fields)

@ -1,13 +1,18 @@
# This package contains tests exercising C++/Rust interop in the cpp kernel.
load("@rules_rust//rust:defs.bzl", "rust_test")
load("//bazel:cc_proto_library.bzl", "cc_proto_library")
load(
"//rust:defs.bzl",
"rust_cc_proto_library",
)
cc_library(
name = "test_utils",
srcs = ["test_utils.cc"],
deps = [
":interop_test_cc_proto",
"//rust/cpp_kernel:cpp_api",
"//src/google/protobuf:unittest_cc_proto",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/strings",
],
@ -17,9 +22,24 @@ rust_test(
name = "interop_test",
srcs = ["main.rs"],
deps = [
":interop_test_cpp_rust_proto",
":test_utils",
"//rust:protobuf_cpp",
"//src/google/protobuf:unittest_cpp_rust_proto",
"@crate_index//:googletest",
],
)
proto_library(
name = "interop_test_proto",
srcs = ["interop_test.proto"],
)
cc_proto_library(
name = "interop_test_cc_proto",
deps = [":interop_test_proto"],
)
rust_cc_proto_library(
name = "interop_test_cpp_rust_proto",
deps = [":interop_test_proto"],
)

@ -0,0 +1,16 @@
edition = "2023";
package rust_cpp_interop_test;
message InteropTestMessage {
int64 i64 = 1;
bytes bytes = 2;
bool b = 3;
int32 default_int32 = 4 [default = 41];
extensions 100 to max;
}
extend InteropTestMessage {
bytes bytes_extension = 100;
}

@ -11,77 +11,79 @@ use protobuf_cpp::prelude::*;
use protobuf_cpp::__runtime::PtrAndLen;
use protobuf_cpp::{MessageMutInterop, MessageViewInterop, OwnedMessageInterop};
use std::ffi::c_void;
use unittest_rust_proto::{TestAllExtensions, TestAllTypes, TestAllTypesMut, TestAllTypesView};
use interop_test_rust_proto::{InteropTestMessage, InteropTestMessageMut, InteropTestMessageView};
macro_rules! proto_assert_eq {
($lhs:expr, $rhs:expr) => {{
let lhs = &$lhs;
let rhs = &$rhs;
assert_that!(lhs.optional_int64(), eq(rhs.optional_int64()));
assert_that!(lhs.optional_bytes(), eq(rhs.optional_bytes()));
assert_that!(lhs.optional_bool(), eq(rhs.optional_bool()));
assert_that!(lhs.i64(), eq(rhs.i64()));
assert_that!(lhs.bytes(), eq(rhs.bytes()));
assert_that!(lhs.b(), eq(rhs.b()));
}};
}
// Helper functions invoking C++ Protobuf APIs directly in C++.
// Defined in `test_utils.cc`.
extern "C" {
fn TakeOwnershipAndGetOptionalInt32(msg: *mut c_void) -> i32;
fn DeserializeTestAllTypes(data: *const u8, len: usize) -> *mut c_void;
fn MutateTestAllTypes(msg: *mut c_void);
fn SerializeTestAllTypes(msg: *const c_void) -> protobuf_cpp::__runtime::SerializedData;
fn DeleteTestAllTypes(msg: *mut c_void);
fn TakeOwnershipAndGetOptionalInt64(msg: *mut c_void) -> i64;
fn DeserializeInteropTestMessage(data: *const u8, len: usize) -> *mut c_void;
fn MutateInteropTestMessage(msg: *mut c_void);
fn SerializeInteropTestMessage(msg: *const c_void) -> protobuf_cpp::__runtime::SerializedData;
fn DeleteInteropTestMessage(msg: *mut c_void);
fn NewWithExtension() -> *mut c_void;
fn GetBytesExtension(msg: *const c_void) -> PtrAndLen;
fn GetConstStaticTestAllTypes() -> *const c_void;
fn GetConstStaticInteropTestMessage() -> *const c_void;
}
#[gtest]
fn send_to_cpp() {
let mut msg1 = TestAllTypes::new();
msg1.set_optional_int32(7);
let i = unsafe { TakeOwnershipAndGetOptionalInt32(msg1.__unstable_leak_raw_message()) };
let mut msg1 = InteropTestMessage::new();
msg1.set_i64(7);
let i = unsafe { TakeOwnershipAndGetOptionalInt64(msg1.__unstable_leak_raw_message()) };
assert_eq!(i, 7);
}
#[gtest]
fn mutate_message_mut_in_cpp() {
let mut msg1 = TestAllTypes::new();
let mut msg1 = InteropTestMessage::new();
unsafe {
MutateTestAllTypes(msg1.as_mut().__unstable_as_raw_message_mut());
MutateInteropTestMessage(msg1.as_mut().__unstable_as_raw_message_mut());
}
let mut msg2 = TestAllTypes::new();
msg2.set_optional_int64(42);
msg2.set_optional_bytes(b"something mysterious");
msg2.set_optional_bool(false);
let mut msg2 = InteropTestMessage::new();
msg2.set_i64(42);
msg2.set_bytes(b"something mysterious");
msg2.set_b(false);
proto_assert_eq!(msg1, msg2);
}
#[gtest]
fn deserialize_in_rust() {
let mut msg1 = TestAllTypes::new();
msg1.set_optional_int64(-1);
msg1.set_optional_bytes(b"some cool data I guess");
let serialized = unsafe { SerializeTestAllTypes(msg1.as_view().__unstable_as_raw_message()) };
let mut msg1 = InteropTestMessage::new();
msg1.set_i64(-1);
msg1.set_bytes(b"some cool data I guess");
let serialized =
unsafe { SerializeInteropTestMessage(msg1.as_view().__unstable_as_raw_message()) };
let msg2 = TestAllTypes::parse(&serialized).unwrap();
let msg2 = InteropTestMessage::parse(&serialized).unwrap();
proto_assert_eq!(msg1, msg2);
}
#[gtest]
fn deserialize_in_cpp() {
let mut msg1 = TestAllTypes::new();
msg1.set_optional_int64(-1);
msg1.set_optional_bytes(b"some cool data I guess");
let mut msg1 = InteropTestMessage::new();
msg1.set_i64(-1);
msg1.set_bytes(b"some cool data I guess");
let data = msg1.serialize().unwrap();
let msg2 = unsafe {
TestAllTypes::__unstable_take_ownership_of_raw_message(DeserializeTestAllTypes(
InteropTestMessage::__unstable_take_ownership_of_raw_message(DeserializeInteropTestMessage(
(*data).as_ptr(),
data.len(),
))
@ -92,38 +94,38 @@ fn deserialize_in_cpp() {
#[gtest]
fn deserialize_in_cpp_into_mut() {
let mut msg1 = TestAllTypes::new();
msg1.set_optional_int64(-1);
msg1.set_optional_bytes(b"some cool data I guess");
let mut msg1 = InteropTestMessage::new();
msg1.set_i64(-1);
msg1.set_bytes(b"some cool data I guess");
let data = msg1.serialize().unwrap();
let mut raw_msg = unsafe { DeserializeTestAllTypes((*data).as_ptr(), data.len()) };
let msg2 = unsafe { TestAllTypesMut::__unstable_wrap_raw_message_mut(&mut raw_msg) };
let mut raw_msg = unsafe { DeserializeInteropTestMessage((*data).as_ptr(), data.len()) };
let msg2 = unsafe { InteropTestMessageMut::__unstable_wrap_raw_message_mut(&mut raw_msg) };
proto_assert_eq!(msg1, msg2);
// The C++ still owns the message here and needs to delete it.
unsafe {
DeleteTestAllTypes(raw_msg);
DeleteInteropTestMessage(raw_msg);
}
}
#[gtest]
fn deserialize_in_cpp_into_view() {
let mut msg1 = TestAllTypes::new();
msg1.set_optional_int64(-1);
msg1.set_optional_bytes(b"some cool data I guess");
let mut msg1 = InteropTestMessage::new();
msg1.set_i64(-1);
msg1.set_bytes(b"some cool data I guess");
let data = msg1.serialize().unwrap();
let raw_msg = unsafe { DeserializeTestAllTypes((*data).as_ptr(), data.len()) };
let raw_msg = unsafe { DeserializeInteropTestMessage((*data).as_ptr(), data.len()) };
let const_msg = raw_msg as *const _;
let msg2 = unsafe { TestAllTypesView::__unstable_wrap_raw_message(&const_msg) };
let msg2 = unsafe { InteropTestMessageView::__unstable_wrap_raw_message(&const_msg) };
proto_assert_eq!(msg1, msg2);
// The C++ still owns the message here and needs to delete it.
unsafe {
DeleteTestAllTypes(raw_msg);
DeleteInteropTestMessage(raw_msg);
}
}
@ -132,10 +134,10 @@ fn deserialize_in_cpp_into_view() {
#[gtest]
fn smuggle_extension() {
let msg1 =
unsafe { TestAllExtensions::__unstable_take_ownership_of_raw_message(NewWithExtension()) };
unsafe { InteropTestMessage::__unstable_take_ownership_of_raw_message(NewWithExtension()) };
let data = msg1.serialize().unwrap();
let mut msg2 = TestAllExtensions::parse(&data).unwrap();
let mut msg2 = InteropTestMessage::parse(&data).unwrap();
let bytes =
unsafe { GetBytesExtension(msg2.as_mut().__unstable_as_raw_message_mut()).as_ref() };
assert_eq!(bytes, b"smuggled");
@ -143,11 +145,11 @@ fn smuggle_extension() {
#[gtest]
fn view_of_const_static() {
let view: TestAllTypesView<'static> = unsafe {
TestAllTypesView::__unstable_wrap_raw_message_unchecked_lifetime(
GetConstStaticTestAllTypes(),
let view: InteropTestMessageView<'static> = unsafe {
InteropTestMessageView::__unstable_wrap_raw_message_unchecked_lifetime(
GetConstStaticInteropTestMessage(),
)
};
assert_eq!(view.optional_int64(), 0);
assert_eq!(view.i64(), 0);
assert_eq!(view.default_int32(), 41);
}

@ -12,55 +12,55 @@
#include "absl/strings/string_view.h"
#include "rust/cpp_kernel/serialized_data.h"
#include "rust/cpp_kernel/strings.h"
#include "google/protobuf/unittest.pb.h"
#include "rust/test/cpp/interop/interop_test.pb.h"
using google::protobuf::rust::SerializedData;
using google::protobuf::rust::SerializeMsg;
using rust_cpp_interop_test::InteropTestMessage;
extern "C" void MutateTestAllTypes(protobuf_unittest::TestAllTypes* msg) {
msg->set_optional_int64(42);
msg->set_optional_bytes("something mysterious");
msg->set_optional_bool(false);
extern "C" void MutateInteropTestMessage(InteropTestMessage* msg) {
msg->set_i64(42);
msg->set_bytes("something mysterious");
msg->set_b(false);
}
extern "C" SerializedData SerializeTestAllTypes(
const protobuf_unittest::TestAllTypes* msg) {
extern "C" SerializedData SerializeInteropTestMessage(
const InteropTestMessage* msg) {
SerializedData data;
ABSL_CHECK(SerializeMsg(msg, &data));
return data;
}
extern "C" void DeleteTestAllTypes(protobuf_unittest::TestAllTypes* msg) {
extern "C" void DeleteInteropTestMessage(InteropTestMessage* msg) {
delete msg;
}
extern "C" void* DeserializeTestAllTypes(const void* data, size_t size) {
auto* proto = new protobuf_unittest::TestAllTypes;
extern "C" void* DeserializeInteropTestMessage(const void* data, size_t size) {
auto* proto = new InteropTestMessage;
proto->ParseFromArray(data, static_cast<int>(size));
return proto;
}
extern "C" void* NewWithExtension() {
auto* proto = new protobuf_unittest::TestAllExtensions;
proto->SetExtension(protobuf_unittest::optional_bytes_extension, "smuggled");
auto* proto = new InteropTestMessage;
proto->SetExtension(rust_cpp_interop_test::bytes_extension, "smuggled");
return proto;
}
extern "C" google::protobuf::rust::PtrAndLen GetBytesExtension(
const protobuf_unittest::TestAllExtensions* proto) {
const InteropTestMessage* proto) {
absl::string_view bytes =
proto->GetExtension(protobuf_unittest::optional_bytes_extension);
proto->GetExtension(rust_cpp_interop_test::bytes_extension);
return {bytes.data(), bytes.size()};
}
extern "C" int32_t TakeOwnershipAndGetOptionalInt32(
protobuf_unittest::TestAllTypes* msg) {
int32_t i = msg->optional_int32();
extern "C" int64_t TakeOwnershipAndGetOptionalInt64(InteropTestMessage* msg) {
int64_t i = msg->i64();
delete msg;
return i;
}
extern "C" const void* GetConstStaticTestAllTypes() {
static const auto* msg = new protobuf_unittest::TestAllTypes;
extern "C" const void* GetConstStaticInteropTestMessage() {
static const auto* msg = new InteropTestMessage;
return msg;
}

Loading…
Cancel
Save