From a8a1fa1096240ee059c30cad9828ea0f9d0c161d Mon Sep 17 00:00:00 2001 From: Ivan Lozano Date: Wed, 30 Oct 2024 18:15:59 +0000 Subject: rust: Add stub support for rust_ffi modules This adds stubs support for rust_ffi and rust_ffi_shared modules. Usage should match current cc usage. The stubs generator leveraged is the cc stubs generator. Bug: 203478530 Test: m blueprint_tests Change-Id: I043b9714a357cd5fe17c183ccdf86900f5172e0e --- rust/library_test.go | 286 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) (limited to 'rust/library_test.go') diff --git a/rust/library_test.go b/rust/library_test.go index e5fd5e018..1198fcc9f 100644 --- a/rust/library_test.go +++ b/rust/library_test.go @@ -482,3 +482,289 @@ func TestRustVersionScriptPropertyErrors(t *testing.T) { extra_exported_symbols: "libbar.map.txt", }`) } + +func TestStubsVersions(t *testing.T) { + t.Parallel() + bp := ` + rust_ffi { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.rs"], + stubs: { + versions: ["29", "R", "current"], + }, + } + ` + ctx := android.GroupFixturePreparers( + prepareForRustTest, + android.PrepareForTestWithVisibility, + rustMockedFiles.AddToFixture(), + android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { + config.TestProductVariables.Platform_version_active_codenames = []string{"R"} + })).RunTestWithBp(t, bp) + + variants := ctx.ModuleVariantsForTests("libfoo") + for _, expectedVer := range []string{"29", "R", "current"} { + expectedVariant := "android_arm_armv7-a-neon_shared_" + expectedVer + if !android.InList(expectedVariant, variants) { + t.Errorf("missing expected variant: %q", expectedVariant) + } + } +} + +func TestStubsVersions_NotSorted(t *testing.T) { + t.Parallel() + bp := ` + rust_ffi_shared { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.rs"], + stubs: { + versions: ["29", "current", "R"], + }, + } + ` + fixture := android.GroupFixturePreparers( + prepareForRustTest, + android.PrepareForTestWithVisibility, + rustMockedFiles.AddToFixture(), + + android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { + config.TestProductVariables.Platform_version_active_codenames = []string{"R"} + })) + + fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`"libfoo" .*: versions: not sorted`)).RunTestWithBp(t, bp) +} + +func TestStubsVersions_ParseError(t *testing.T) { + t.Parallel() + bp := ` + rust_ffi_shared { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.rs"], + stubs: { + versions: ["29", "current", "X"], + }, + } + ` + fixture := android.GroupFixturePreparers( + prepareForRustTest, + android.PrepareForTestWithVisibility, + rustMockedFiles.AddToFixture(), + + android.FixtureModifyConfigAndContext(func(config android.Config, ctx *android.TestContext) { + config.TestProductVariables.Platform_version_active_codenames = []string{"R"} + })) + + fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`)).RunTestWithBp(t, bp) +} + +func TestVersionedStubs(t *testing.T) { + t.Parallel() + bp := ` + rust_ffi_shared { + name: "libFoo", + crate_name: "Foo", + srcs: ["foo.rs"], + stubs: { + symbol_file: "foo.map.txt", + versions: ["1", "2", "3"], + }, + } + + cc_library_shared { + name: "libBar", + srcs: ["bar.c"], + shared_libs: ["libFoo#1"], + } + + rust_library { + name: "libbar_rs", + crate_name: "bar_rs", + srcs: ["bar.rs"], + shared_libs: ["libFoo#1"], + } + rust_ffi { + name: "libbar_ffi_rs", + crate_name: "bar_ffi_rs", + srcs: ["bar.rs"], + shared_libs: ["libFoo#1"], + } + ` + + ctx := android.GroupFixturePreparers( + prepareForRustTest, + android.PrepareForTestWithVisibility, + rustMockedFiles.AddToFixture()).RunTestWithBp(t, bp) + + variants := ctx.ModuleVariantsForTests("libFoo") + expectedVariants := []string{ + "android_arm64_armv8-a_shared", + "android_arm64_armv8-a_shared_1", + "android_arm64_armv8-a_shared_2", + "android_arm64_armv8-a_shared_3", + "android_arm64_armv8-a_shared_current", + "android_arm_armv7-a-neon_shared", + "android_arm_armv7-a-neon_shared_1", + "android_arm_armv7-a-neon_shared_2", + "android_arm_armv7-a-neon_shared_3", + "android_arm_armv7-a-neon_shared_current", + } + variantsMismatch := false + if len(variants) != len(expectedVariants) { + variantsMismatch = true + } else { + for _, v := range expectedVariants { + if !android.InList(v, variants) { + variantsMismatch = false + } + } + } + if variantsMismatch { + t.Errorf("variants of libFoo expected:\n") + for _, v := range expectedVariants { + t.Errorf("%q\n", v) + } + t.Errorf(", but got:\n") + for _, v := range variants { + t.Errorf("%q\n", v) + } + } + + libBarLinkRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_shared").Rule("ld") + libBarFlags := libBarLinkRule.Args["libFlags"] + + libBarRsRustcRule := ctx.ModuleForTests("libbar_rs", "android_arm64_armv8-a_dylib").Rule("rustc") + libBarRsFlags := libBarRsRustcRule.Args["linkFlags"] + + libBarFfiRsRustcRule := ctx.ModuleForTests("libbar_ffi_rs", "android_arm64_armv8-a_shared").Rule("rustc") + libBarFfiRsFlags := libBarFfiRsRustcRule.Args["linkFlags"] + + libFoo1StubPath := "libFoo/android_arm64_armv8-a_shared_1/unstripped/libFoo.so" + if !strings.Contains(libBarFlags, libFoo1StubPath) { + t.Errorf("%q is not found in %q", libFoo1StubPath, libBarFlags) + } + if !strings.Contains(libBarRsFlags, libFoo1StubPath) { + t.Errorf("%q is not found in %q", libFoo1StubPath, libBarRsFlags) + } + if !strings.Contains(libBarFfiRsFlags, libFoo1StubPath) { + t.Errorf("%q is not found in %q", libFoo1StubPath, libBarFfiRsFlags) + } +} + +func TestCheckConflictingExplicitVersions(t *testing.T) { + t.Parallel() + bp := ` + cc_library_shared { + name: "libbar", + srcs: ["bar.c"], + shared_libs: ["libfoo", "libfoo#impl"], + } + + rust_ffi_shared { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.rs"], + stubs: { + versions: ["29", "current"], + }, + } + ` + fixture := android.GroupFixturePreparers( + prepareForRustTest, + android.PrepareForTestWithVisibility, + rustMockedFiles.AddToFixture()) + + fixture.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(`duplicate shared libraries with different explicit versions`)).RunTestWithBp(t, bp) +} + +func TestAddnoOverride64GlobalCflags(t *testing.T) { + t.Parallel() + bp := ` + cc_library_shared { + name: "libclient", + srcs: ["foo.c"], + shared_libs: ["libfoo#1"], + } + + rust_ffi_shared { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.c"], + shared_libs: ["libbar"], + stubs: { + symbol_file: "foo.map.txt", + versions: ["1", "2", "3"], + }, + } + + cc_library_shared { + name: "libbar", + export_include_dirs: ["include/libbar"], + srcs: ["foo.c"], + }` + ctx := android.GroupFixturePreparers( + prepareForRustTest, + android.PrepareForTestWithVisibility, + rustMockedFiles.AddToFixture()).RunTestWithBp(t, bp) + + cFlags := ctx.ModuleForTests("libclient", "android_arm64_armv8-a_shared").Rule("cc").Args["cFlags"] + + if !strings.Contains(cFlags, "${config.NoOverride64GlobalCflags}") { + t.Errorf("expected %q in cflags, got %q", "${config.NoOverride64GlobalCflags}", cFlags) + } +} + +// Make sure the stubs properties can only be used in modules producing shared libs +func TestRustStubsFFIOnly(t *testing.T) { + testRustError(t, "stubs properties", ` + rust_library { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.c"], + shared_libs: ["libbar"], + stubs: { + symbol_file: "foo.map.txt", + }, + } + `) + + testRustError(t, "stubs properties", ` + rust_library { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.c"], + shared_libs: ["libbar"], + stubs: { + versions: ["1"], + }, + } + `) + + testRustError(t, "stubs properties", ` + rust_ffi_static { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.c"], + shared_libs: ["libbar"], + stubs: { + symbol_file: "foo.map.txt", + }, + } + `) + testRustError(t, "stubs properties", ` + rust_ffi_static { + name: "libfoo", + crate_name: "foo", + srcs: ["foo.c"], + shared_libs: ["libbar"], + stubs: { + versions: ["1"], + }, + } + `) +} + +// TODO: When rust_ffi libraries support export_*_lib_headers, +// add a test similar to cc.TestStubsLibReexportsHeaders -- cgit v1.2.3-59-g8ed1b