| // Copyright 2020 The Android Open Source Project |
| // |
| // 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. |
| |
| package rust |
| |
| import ( |
| "strings" |
| "testing" |
| |
| "android/soong/android" |
| "android/soong/cc" |
| ) |
| |
| // Test that cc modules can link against vendor_available rust_ffi_rlib/rust_ffi_static libraries. |
| func TestVendorLinkage(t *testing.T) { |
| ctx := testRust(t, ` |
| cc_binary { |
| name: "fizz_vendor_available", |
| static_libs: ["libfoo_vendor_static"], |
| static_rlibs: ["libfoo_vendor"], |
| vendor_available: true, |
| } |
| cc_binary { |
| name: "fizz_soc_specific", |
| static_rlibs: ["libfoo_vendor"], |
| soc_specific: true, |
| } |
| rust_ffi_rlib { |
| name: "libfoo_vendor", |
| crate_name: "foo", |
| srcs: ["foo.rs"], |
| vendor_available: true, |
| } |
| rust_ffi_static { |
| name: "libfoo_vendor_static", |
| crate_name: "foo", |
| srcs: ["foo.rs"], |
| vendor_available: true, |
| } |
| `) |
| |
| vendorBinary := ctx.ModuleForTests("fizz_vendor_available", "android_vendor_arm64_armv8-a").Module().(*cc.Module) |
| |
| if !android.InList("libfoo_vendor_static.vendor", vendorBinary.Properties.AndroidMkStaticLibs) { |
| t.Errorf("vendorBinary should have a dependency on libfoo_vendor_static.vendor: %#v", vendorBinary.Properties.AndroidMkStaticLibs) |
| } |
| } |
| |
| // Test that variants which use the vndk emit the appropriate cfg flag. |
| func TestImageCfgFlag(t *testing.T) { |
| ctx := testRust(t, ` |
| rust_ffi_shared { |
| name: "libfoo", |
| crate_name: "foo", |
| srcs: ["foo.rs"], |
| vendor_available: true, |
| product_available: true, |
| } |
| `) |
| |
| vendor := ctx.ModuleForTests("libfoo", "android_vendor_arm64_armv8-a_shared").Rule("rustc") |
| |
| if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vndk'") { |
| t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) |
| } |
| if !strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_vendor'") { |
| t.Errorf("missing \"--cfg 'android_vendor'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) |
| } |
| if strings.Contains(vendor.Args["rustcFlags"], "--cfg 'android_product'") { |
| t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo vendor variant, rustcFlags: %#v", vendor.Args["rustcFlags"]) |
| } |
| |
| product := ctx.ModuleForTests("libfoo", "android_product_arm64_armv8-a_shared").Rule("rustc") |
| if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vndk'") { |
| t.Errorf("missing \"--cfg 'android_vndk'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) |
| } |
| if strings.Contains(product.Args["rustcFlags"], "--cfg 'android_vendor'") { |
| t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) |
| } |
| if !strings.Contains(product.Args["rustcFlags"], "--cfg 'android_product'") { |
| t.Errorf("missing \"--cfg 'android_product'\" for libfoo product variant, rustcFlags: %#v", product.Args["rustcFlags"]) |
| } |
| |
| system := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("rustc") |
| if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vndk'") { |
| t.Errorf("unexpected \"--cfg 'android_vndk'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"]) |
| } |
| if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_vendor'") { |
| t.Errorf("unexpected \"--cfg 'android_vendor'\" for libfoo system variant, rustcFlags: %#v", system.Args["rustcFlags"]) |
| } |
| if strings.Contains(system.Args["rustcFlags"], "--cfg 'android_product'") { |
| t.Errorf("unexpected \"--cfg 'android_product'\" for libfoo system variant, rustcFlags: %#v", product.Args["rustcFlags"]) |
| } |
| |
| } |
| |
| // Test that cc modules can link against vendor_ramdisk_available rust_ffi_rlib and rust_ffi_static libraries. |
| func TestVendorRamdiskLinkage(t *testing.T) { |
| ctx := testRust(t, ` |
| cc_library_shared { |
| name: "libcc_vendor_ramdisk", |
| static_rlibs: ["libfoo_vendor_ramdisk"], |
| static_libs: ["libfoo_static_vendor_ramdisk"], |
| system_shared_libs: [], |
| vendor_ramdisk_available: true, |
| } |
| rust_ffi_rlib { |
| name: "libfoo_vendor_ramdisk", |
| crate_name: "foo", |
| srcs: ["foo.rs"], |
| vendor_ramdisk_available: true, |
| } |
| rust_ffi_static { |
| name: "libfoo_static_vendor_ramdisk", |
| crate_name: "foo", |
| srcs: ["foo.rs"], |
| vendor_ramdisk_available: true, |
| } |
| `) |
| |
| vendorRamdiskLibrary := ctx.ModuleForTests("libcc_vendor_ramdisk", "android_vendor_ramdisk_arm64_armv8-a_shared").Module().(*cc.Module) |
| |
| if !android.InList("libfoo_static_vendor_ramdisk.vendor_ramdisk", vendorRamdiskLibrary.Properties.AndroidMkStaticLibs) { |
| t.Errorf("libcc_vendor_ramdisk should have a dependency on libfoo_static_vendor_ramdisk") |
| } |
| } |
| |
| // Test that prebuilt libraries cannot be made vendor available. |
| func TestForbiddenVendorLinkage(t *testing.T) { |
| testRustError(t, "Rust prebuilt modules not supported for non-system images.", ` |
| rust_prebuilt_library { |
| name: "librust_prebuilt", |
| crate_name: "rust_prebuilt", |
| rlib: { |
| srcs: ["libtest.rlib"], |
| }, |
| dylib: { |
| srcs: ["libtest.so"], |
| }, |
| vendor: true, |
| } |
| `) |
| } |
| |
| func checkInstallPartition(t *testing.T, ctx *android.TestContext, name, variant, expected string) { |
| mod := ctx.ModuleForTests(name, variant).Module().(*Module) |
| partitionDefined := false |
| checkPartition := func(specific bool, partition string) { |
| if specific { |
| if expected != partition && !partitionDefined { |
| // The variant is installed to the 'partition' |
| t.Errorf("%s variant of %q must not be installed to %s partition", variant, name, partition) |
| } |
| partitionDefined = true |
| } else { |
| // The variant is not installed to the 'partition' |
| if expected == partition { |
| t.Errorf("%s variant of %q must be installed to %s partition", variant, name, partition) |
| } |
| } |
| } |
| socSpecific := func(m *Module) bool { |
| return m.SocSpecific() |
| } |
| deviceSpecific := func(m *Module) bool { |
| return m.DeviceSpecific() |
| } |
| productSpecific := func(m *Module) bool { |
| return m.ProductSpecific() || m.productSpecificModuleContext() |
| } |
| systemExtSpecific := func(m *Module) bool { |
| return m.SystemExtSpecific() |
| } |
| checkPartition(socSpecific(mod), "vendor") |
| checkPartition(deviceSpecific(mod), "odm") |
| checkPartition(productSpecific(mod), "product") |
| checkPartition(systemExtSpecific(mod), "system_ext") |
| if !partitionDefined && expected != "system" { |
| t.Errorf("%s variant of %q is expected to be installed to %s partition,"+ |
| " but installed to system partition", variant, name, expected) |
| } |
| } |
| |
| func TestInstallPartition(t *testing.T) { |
| t.Parallel() |
| t.Helper() |
| ctx := testRust(t, ` |
| rust_binary { |
| name: "sample_system", |
| crate_name: "sample", |
| srcs: ["foo.rs"], |
| } |
| rust_binary { |
| name: "sample_system_ext", |
| crate_name: "sample", |
| srcs: ["foo.rs"], |
| system_ext_specific: true, |
| } |
| rust_binary { |
| name: "sample_product", |
| crate_name: "sample", |
| srcs: ["foo.rs"], |
| product_specific: true, |
| } |
| rust_binary { |
| name: "sample_vendor", |
| crate_name: "sample", |
| srcs: ["foo.rs"], |
| vendor: true, |
| } |
| rust_binary { |
| name: "sample_odm", |
| crate_name: "sample", |
| srcs: ["foo.rs"], |
| device_specific: true, |
| } |
| rust_binary { |
| name: "sample_all_available", |
| crate_name: "sample", |
| srcs: ["foo.rs"], |
| vendor_available: true, |
| product_available: true, |
| } |
| `) |
| |
| checkInstallPartition(t, ctx, "sample_system", binaryCoreVariant, "system") |
| checkInstallPartition(t, ctx, "sample_system_ext", binaryCoreVariant, "system_ext") |
| checkInstallPartition(t, ctx, "sample_product", binaryProductVariant, "product") |
| checkInstallPartition(t, ctx, "sample_vendor", binaryVendorVariant, "vendor") |
| checkInstallPartition(t, ctx, "sample_odm", binaryVendorVariant, "odm") |
| |
| checkInstallPartition(t, ctx, "sample_all_available", binaryCoreVariant, "system") |
| } |