blob: 14c0b6394f3a8e4922055ca472e7cc34174ebd6d [file] [log] [blame]
// Copyright 2024 Google Inc. All rights reserved.
//
// 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 apex
import (
"testing"
"android/soong/aconfig/codegen"
"android/soong/android"
"android/soong/cc"
"android/soong/genrule"
"android/soong/java"
"android/soong/rust"
"github.com/google/blueprint/proptools"
)
var withAconfigValidationError = android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.AconfigContainerValidation = "error"
variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
})
func TestValidationAcrossContainersExportedPass(t *testing.T) {
testCases := []struct {
name string
bp string
}{
{
name: "Java lib passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
],
updatable: false,
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
exportable: true,
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
mode: "exported",
apex_available: [
"myapex",
],
}`,
},
{
name: "Android app passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
apps: [
"my_android_app_foo",
],
updatable: false,
}
android_app {
name: "my_android_app_foo",
srcs: ["foo/MyClass.java"],
sdk_version: "none",
system_modules: "none",
stl: "none",
static_libs: ["my_java_library_bar"],
apex_available: [ "myapex" ],
}
java_library {
name: "my_java_library_bar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_bar"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
exportable: true,
}
java_aconfig_library {
name: "my_java_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
mode: "exported",
apex_available: [
"myapex",
],
}`,
},
{
name: "Cc lib passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
native_shared_libs: [
"my_cc_library_bar",
],
binaries: [
"my_cc_binary_baz",
],
updatable: false,
}
cc_library {
name: "my_cc_library_bar",
srcs: ["foo/bar/MyClass.cc"],
static_libs: [
"my_cc_aconfig_library_bar",
"my_cc_aconfig_library_baz",
],
apex_available: [
"myapex",
],
}
cc_binary {
name: "my_cc_binary_baz",
srcs: ["foo/bar/MyClass.cc"],
static_libs: ["my_cc_aconfig_library_baz"],
apex_available: [
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
cc_library {
name: "libbase",
srcs: ["libbase.cc"],
apex_available: [
"myapex",
],
}
cc_library {
name: "libaconfig_storage_read_api_cc",
srcs: ["libaconfig_storage_read_api_cc.cc"],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
exportable: true,
}
cc_aconfig_library {
name: "my_cc_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
apex_available: [
"myapex",
],
mode: "exported",
}
aconfig_declarations {
name: "my_aconfig_declarations_baz",
package: "com.example.package",
container: "otherapex",
srcs: ["baz.aconfig"],
exportable: true,
}
cc_aconfig_library {
name: "my_cc_aconfig_library_baz",
aconfig_declarations: "my_aconfig_declarations_baz",
apex_available: [
"myapex",
],
mode: "exported",
}`,
},
{
name: "Rust lib passes for exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
native_shared_libs: ["libmy_rust_library"],
binaries: ["my_rust_binary"],
updatable: false,
}
rust_library {
name: "libflags_rust", // test mock
crate_name: "flags_rust",
srcs: ["lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblazy_static", // test mock
crate_name: "lazy_static",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "libaconfig_storage_read_api", // test mock
crate_name: "aconfig_storage_read_api",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblogger", // test mock
crate_name: "logger",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblog_rust", // test mock
crate_name: "log_rust",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_ffi_shared {
name: "libmy_rust_library",
srcs: ["src/lib.rs"],
rustlibs: ["libmy_rust_aconfig_library_foo"],
crate_name: "my_rust_library",
apex_available: ["myapex"],
}
rust_binary {
name: "my_rust_binary",
srcs: ["foo/bar/MyClass.rs"],
rustlibs: ["libmy_rust_aconfig_library_bar"],
apex_available: ["myapex"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
rust_aconfig_library {
name: "libmy_rust_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
crate_name: "my_rust_aconfig_library_foo",
apex_available: ["myapex"],
mode: "exported",
}
rust_aconfig_library {
name: "libmy_rust_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
crate_name: "my_rust_aconfig_library_bar",
apex_available: ["myapex"],
mode: "exported",
}`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcBuildComponents,
rust.PrepareForTestWithRustDefaultModules,
codegen.PrepareForTestWithAconfigBuildComponents,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
withAconfigValidationError,
).
RunTestWithBp(t, test.bp)
})
}
}
func TestValidationAcrossContainersNotExportedFail(t *testing.T) {
testCases := []struct {
name string
expectedError string
bp string
}{
{
name: "Java lib fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_foo",
],
updatable: false,
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_java_library_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Android app fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
apps: [
"my_android_app_foo",
],
updatable: false,
}
android_app {
name: "my_android_app_foo",
srcs: ["foo/MyClass.java"],
sdk_version: "none",
system_modules: "none",
stl: "none",
static_libs: ["my_java_library_foo"],
apex_available: [ "myapex" ],
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Cc lib fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
native_shared_libs: [
"my_cc_library_foo",
],
updatable: false,
}
cc_library {
name: "my_cc_library_foo",
srcs: ["foo/bar/MyClass.cc"],
shared_libs: [
"my_cc_aconfig_library_foo",
],
apex_available: [
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
cc_library {
name: "libbase",
srcs: ["libbase.cc"],
apex_available: [
"myapex",
],
}
cc_library {
name: "libaconfig_storage_read_api_cc",
srcs: ["libaconfig_storage_read_api_cc.cc"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
cc_aconfig_library {
name: "my_cc_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_cc_library_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Cc binary fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
binaries: [
"my_cc_binary_foo",
],
updatable: false,
}
cc_library {
name: "my_cc_library_foo",
srcs: ["foo/bar/MyClass.cc"],
static_libs: [
"my_cc_aconfig_library_foo",
],
apex_available: [
"myapex",
],
}
cc_binary {
name: "my_cc_binary_foo",
srcs: ["foo/bar/MyClass.cc"],
static_libs: ["my_cc_library_foo"],
apex_available: [
"myapex",
],
}
cc_library {
name: "server_configurable_flags",
srcs: ["server_configurable_flags.cc"],
}
cc_library {
name: "libbase",
srcs: ["libbase.cc"],
apex_available: [
"myapex",
],
}
cc_library {
name: "libaconfig_storage_read_api_cc",
srcs: ["libaconfig_storage_read_api_cc.cc"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
cc_aconfig_library {
name: "my_cc_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_cc_binary_foo/myapex depends on my_cc_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Rust lib fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
native_shared_libs: ["libmy_rust_library"],
updatable: false,
}
rust_library {
name: "libflags_rust", // test mock
crate_name: "flags_rust",
srcs: ["lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblazy_static", // test mock
crate_name: "lazy_static",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "libaconfig_storage_read_api", // test mock
crate_name: "aconfig_storage_read_api",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblogger", // test mock
crate_name: "logger",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblog_rust", // test mock
crate_name: "log_rust",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_ffi_shared {
name: "libmy_rust_library",
srcs: ["src/lib.rs"],
rustlibs: ["libmy_rust_aconfig_library_foo"],
crate_name: "my_rust_library",
apex_available: ["myapex"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
rust_aconfig_library {
name: "libmy_rust_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
crate_name: "my_rust_aconfig_library_foo",
apex_available: ["myapex"],
}`,
expectedError: `.*libmy_rust_aconfig_library_foo/myapex depends on libmy_rust_aconfig_library_foo/otherapex/production across containers`,
},
{
name: "Rust binary fails for non-exported containers cross",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
binaries: ["my_rust_binary"],
updatable: false,
}
rust_library {
name: "libflags_rust", // test mock
crate_name: "flags_rust",
srcs: ["lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblazy_static", // test mock
crate_name: "lazy_static",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "libaconfig_storage_read_api", // test mock
crate_name: "aconfig_storage_read_api",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblogger", // test mock
crate_name: "logger",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_library {
name: "liblog_rust", // test mock
crate_name: "log_rust",
srcs: ["src/lib.rs"],
apex_available: ["myapex"],
}
rust_binary {
name: "my_rust_binary",
srcs: ["foo/bar/MyClass.rs"],
rustlibs: ["libmy_rust_aconfig_library_bar"],
apex_available: ["myapex"],
}
aconfig_declarations {
name: "my_aconfig_declarations_bar",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
rust_aconfig_library {
name: "libmy_rust_aconfig_library_bar",
aconfig_declarations: "my_aconfig_declarations_bar",
crate_name: "my_rust_aconfig_library_bar",
apex_available: ["myapex"],
}`,
expectedError: `.*libmy_rust_aconfig_library_bar/myapex depends on libmy_rust_aconfig_library_bar/otherapex/production across containers`,
},
{
name: "Aconfig validation propagate along sourceOrOutputDependencyTag",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
apps: [
"my_android_app_foo",
],
updatable: false,
}
android_app {
name: "my_android_app_foo",
srcs: ["foo/MyClass.java"],
sdk_version: "none",
system_modules: "none",
stl: "none",
static_libs: ["my_java_library_foo"],
apex_available: [ "myapex" ],
}
java_library {
name: "my_java_library_foo",
srcs: [":my_genrule_foo"],
sdk_version: "none",
system_modules: "none",
apex_available: [
"myapex",
],
}
aconfig_declarations_group {
name: "my_aconfig_declarations_group_foo",
java_aconfig_libraries: [
"my_java_aconfig_library_foo",
],
}
filegroup {
name: "my_filegroup_foo_srcjars",
srcs: [
":my_aconfig_declarations_group_foo{.srcjars}",
],
}
genrule {
name: "my_genrule_foo",
srcs: [":my_filegroup_foo_srcjars"],
cmd: "cp $(in) $(out)",
out: ["my_genrule_foo.srcjar"],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["bar.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
errorHandler := android.FixtureExpectsNoErrors
if test.expectedError != "" {
errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
}
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcBuildComponents,
rust.PrepareForTestWithRustDefaultModules,
codegen.PrepareForTestWithAconfigBuildComponents,
genrule.PrepareForIntegrationTestWithGenrule,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
withAconfigValidationError,
).
ExtendWithErrorHandler(errorHandler).
RunTestWithBp(t, test.bp)
})
}
}
func TestValidationNotPropagateAcrossShared(t *testing.T) {
testCases := []struct {
name string
bp string
}{
{
name: "Java shared lib not propagate aconfig validation",
bp: apex_default_bp + `
apex {
name: "myapex",
manifest: ":myapex.manifest",
androidManifest: ":myapex.androidmanifest",
key: "myapex.key",
java_libs: [
"my_java_library_bar",
],
updatable: false,
}
java_library {
name: "my_java_library_bar",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
libs: ["my_java_library_foo"],
apex_available: [
"myapex",
],
}
java_library {
name: "my_java_library_foo",
srcs: ["foo/bar/MyClass.java"],
sdk_version: "none",
system_modules: "none",
static_libs: ["my_java_aconfig_library_foo"],
apex_available: [
"myapex",
],
}
aconfig_declarations {
name: "my_aconfig_declarations_foo",
package: "com.example.package",
container: "otherapex",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
name: "my_java_aconfig_library_foo",
aconfig_declarations: "my_aconfig_declarations_foo",
apex_available: [
"myapex",
],
}`,
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
cc.PrepareForTestWithCcBuildComponents,
rust.PrepareForTestWithRustDefaultModules,
codegen.PrepareForTestWithAconfigBuildComponents,
PrepareForTestWithApexBuildComponents,
prepareForTestWithMyapex,
withAconfigValidationError,
).
RunTestWithBp(t, test.bp)
})
}
}