2021-06-01 22:18:08 +02:00
// Copyright 2021 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 java
import (
"fmt"
"path/filepath"
"regexp"
Allow sdk_version: "system_server_current" modules to access module-lib APIs
Previously, a java module with sdk_version: "system_server_current",
would only be able to access the system server or public API of a
java_sdk_library. This change allows it to access the system server,
module lib, system and public APIs in that order.
The apiScope structs define the characteristics of each of the
different API scopes used as required by the java_sdk_library. They are
organized into a hierarchy which is used for two different purposes.
The first purpose is to define an extension hierachy. If scope X
extends Y then X provides a superset of all API elements (classes,
fields, methods, etc) provided by Y. That is reflected in the fact that
the .txt file for X would be a delta on the .txt file for Y. So, system
extends public and so system_current.txt only contains additional API
elements to add to current.txt.
The second purpose is when a java_sdk_library/import is asked to
provide a specific API scope. e.g. a library that has:
sdk_version: "module_current"
will ask each of the SDK libraries it depends upon for a module-lib
API. However, not all of them will provide an API for that scope. In
that case it will find the closest suitable API scope.
Previously, it did that by traversing up the API extension until it
found an API scope that it did provide and return that. As
system_server_current extended the public API that meant that a library
which has:
sdk_version: "system_server_current"
would provide a system server API if available, and if not fall
straight back to public. That meant that the library could not access
system or module-lib APIs even though it is running in the system
server which should be able to access all APIs.
One way to fix this would have been to just have system server API
scope extend module-lib but that would have had a number of nasty
side effects:
* It would have created a significant overhead as every module that
provides a system server API would also have to provide a module-lib
and system API, along with their corresponding .txt files.
* Each existing java_sdk_library that provided a system server API
would need those .txt files created.
* Generating sdk snapshots for older releases would have been more
complicated.
* It would have confused developers.
All of that would be unnecessary because the system server API scope is
intended to be provided by libraries that are used solely by the system
server so there is no point in them providing anything other than a
system server API.
So, instead a separate access hierarchy was added which is the same as
the extension hierarchy for all existing scopes except for the
system server scope, which instead of just being able to access the
public API will be able to access the module-lib scope, which can in
turn access system and it can in turn access public.
That achieves what we want which is a library that is loaded into the
system server to be able to access all API scopes.
Bug: 204176972
Test: m nothing
Change-Id: I854df63fcaeba32afbc1eb0d1a501238022673d0
2022-09-30 19:11:41 +02:00
"strings"
2021-06-01 22:18:08 +02:00
"testing"
2021-09-28 17:40:23 +02:00
"android/soong/android"
2021-06-01 22:18:08 +02:00
"github.com/google/blueprint/proptools"
)
func TestJavaSdkLibrary ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"28" : { "foo" } ,
"29" : { "foo" } ,
"30" : { "bar" , "barney" , "baz" , "betty" , "foo" , "fred" , "quuz" , "wilma" } ,
} ) ,
2023-03-23 18:44:51 +01:00
android . FixtureModifyConfig ( func ( config android . Config ) {
config . SetApiLibraries ( [ ] string { "foo" } )
} ) ,
2023-12-26 20:08:01 +01:00
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_HIDDEN_API_EXPORTABLE_STUBS" : "true" ,
}
} ) ,
2021-06-01 22:18:08 +02:00
) . RunTestWithBp ( t , `
droiddoc_exported_dir {
name : "droiddoc-templates-sdk" ,
path : "." ,
}
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
}
java_sdk_library {
name : "bar" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "bar" ] ,
2021-12-06 22:35:11 +01:00
exclude_kotlinc_generated_files : true ,
2021-06-01 22:18:08 +02:00
}
java_library {
name : "baz" ,
srcs : [ "c.java" ] ,
libs : [ "foo" , "bar.stubs" ] ,
sdk_version : "system_current" ,
}
java_sdk_library {
name : "barney" ,
srcs : [ "c.java" ] ,
api_only : true ,
}
java_sdk_library {
name : "betty" ,
srcs : [ "c.java" ] ,
shared_library : false ,
}
java_sdk_library_import {
name : "quuz" ,
public : {
jars : [ "c.jar" ] ,
2023-09-13 03:01:53 +02:00
current_api : "api/current.txt" ,
removed_api : "api/removed.txt" ,
2021-06-01 22:18:08 +02:00
} ,
}
java_sdk_library_import {
name : "fred" ,
public : {
jars : [ "b.jar" ] ,
} ,
}
java_sdk_library_import {
name : "wilma" ,
public : {
jars : [ "b.jar" ] ,
} ,
shared_library : false ,
}
java_library {
name : "qux" ,
srcs : [ "c.java" ] ,
libs : [ "baz" , "fred" , "quuz.stubs" , "wilma" , "barney" , "betty" ] ,
sdk_version : "system_current" ,
}
java_library {
name : "baz-test" ,
srcs : [ "c.java" ] ,
libs : [ "foo" ] ,
sdk_version : "test_current" ,
}
java_library {
name : "baz-29" ,
srcs : [ "c.java" ] ,
libs : [ "foo" ] ,
sdk_version : "system_29" ,
}
java_library {
name : "baz-module-30" ,
srcs : [ "c.java" ] ,
libs : [ "foo" ] ,
sdk_version : "module_30" ,
}
2021-09-07 19:21:59 +02:00
` )
2021-06-01 22:18:08 +02:00
// check the existence of the internal modules
Remove duplicate component from sdk snapshot
Previously, an sdk snapshot could contain the following:
* A java_sdk_library_import module, e.g. "foo" which creates component
modules "foo.stubs", etc.
* A corresponding versioned module, e.g. "sdk_foo@current" which
created component modules "sdk_foo@current.stubs", etc.
* An internal (to the sdk snapshot) java_import for one of "foo"'s
components, e.g. "sdk_foo.stubs"
* A corresponding versioned module, e.g. "sdk_foo.stubs@current".
That causes a few problems:
1. The "foo.stubs" is duplicated.
2. The names of the components created by the versioned
java_sdk_library_import are invalid, as they append the component's
suffix to the version and not the name before the version.
The latter causes problems when building against prebuilts and fixing
that causes the generated snapshot to be invalid because it contains
duplicate definitions of the "sdk_foo.stubs@current" module. One
explicitly in the Android.bp file and one created by the
"sdk_foo@current" module.
Removing the duplicates from the snapshot causes errors as the name
generated by the snapshot for the component module, i.e.
"sdk_foo.stubs@current" does not match the name generated by the
"sdk_foo@current", i.e. "sdk_foo@current.stubs".
This change fixes them together.
Bug: 179354495
Test: m nothing
Merged-In: I515f235fe21755b5275af12366e96c24c94c0273
Change-Id: I515f235fe21755b5275af12366e96c24c94c0273
(cherry picked from commit a1aa7387f74a49c8c974ba2198def0e081488624)
2021-04-29 22:50:40 +02:00
foo := result . ModuleForTests ( "foo" , "android_common" )
2021-06-01 22:18:08 +02:00
result . ModuleForTests ( apiScopePublic . stubsLibraryModuleName ( "foo" ) , "android_common" )
result . ModuleForTests ( apiScopeSystem . stubsLibraryModuleName ( "foo" ) , "android_common" )
result . ModuleForTests ( apiScopeTest . stubsLibraryModuleName ( "foo" ) , "android_common" )
result . ModuleForTests ( apiScopePublic . stubsSourceModuleName ( "foo" ) , "android_common" )
result . ModuleForTests ( apiScopeSystem . stubsSourceModuleName ( "foo" ) , "android_common" )
result . ModuleForTests ( apiScopeTest . stubsSourceModuleName ( "foo" ) , "android_common" )
2023-02-02 23:32:31 +01:00
result . ModuleForTests ( apiScopePublic . stubsSourceModuleName ( "foo" ) + ".api.contribution" , "" )
2023-03-23 18:44:51 +01:00
result . ModuleForTests ( apiScopePublic . apiLibraryModuleName ( "foo" ) , "android_common" )
2021-06-01 22:18:08 +02:00
result . ModuleForTests ( "foo" + sdkXmlFileSuffix , "android_common" )
result . ModuleForTests ( "foo.api.public.28" , "" )
result . ModuleForTests ( "foo.api.system.28" , "" )
result . ModuleForTests ( "foo.api.test.28" , "" )
2023-12-14 23:46:23 +01:00
exportedComponentsInfo , _ := android . SingletonModuleProvider ( result , foo . Module ( ) , android . ExportedComponentsInfoProvider )
Remove duplicate component from sdk snapshot
Previously, an sdk snapshot could contain the following:
* A java_sdk_library_import module, e.g. "foo" which creates component
modules "foo.stubs", etc.
* A corresponding versioned module, e.g. "sdk_foo@current" which
created component modules "sdk_foo@current.stubs", etc.
* An internal (to the sdk snapshot) java_import for one of "foo"'s
components, e.g. "sdk_foo.stubs"
* A corresponding versioned module, e.g. "sdk_foo.stubs@current".
That causes a few problems:
1. The "foo.stubs" is duplicated.
2. The names of the components created by the versioned
java_sdk_library_import are invalid, as they append the component's
suffix to the version and not the name before the version.
The latter causes problems when building against prebuilts and fixing
that causes the generated snapshot to be invalid because it contains
duplicate definitions of the "sdk_foo.stubs@current" module. One
explicitly in the Android.bp file and one created by the
"sdk_foo@current" module.
Removing the duplicates from the snapshot causes errors as the name
generated by the snapshot for the component module, i.e.
"sdk_foo.stubs@current" does not match the name generated by the
"sdk_foo@current", i.e. "sdk_foo@current.stubs".
This change fixes them together.
Bug: 179354495
Test: m nothing
Merged-In: I515f235fe21755b5275af12366e96c24c94c0273
Change-Id: I515f235fe21755b5275af12366e96c24c94c0273
(cherry picked from commit a1aa7387f74a49c8c974ba2198def0e081488624)
2021-04-29 22:50:40 +02:00
expectedFooExportedComponents := [ ] string {
2024-03-20 22:29:39 +01:00
"foo-removed.api.combined.public.latest" ,
"foo-removed.api.combined.system.latest" ,
"foo.api.combined.public.latest" ,
"foo.api.combined.system.latest" ,
Remove duplicate component from sdk snapshot
Previously, an sdk snapshot could contain the following:
* A java_sdk_library_import module, e.g. "foo" which creates component
modules "foo.stubs", etc.
* A corresponding versioned module, e.g. "sdk_foo@current" which
created component modules "sdk_foo@current.stubs", etc.
* An internal (to the sdk snapshot) java_import for one of "foo"'s
components, e.g. "sdk_foo.stubs"
* A corresponding versioned module, e.g. "sdk_foo.stubs@current".
That causes a few problems:
1. The "foo.stubs" is duplicated.
2. The names of the components created by the versioned
java_sdk_library_import are invalid, as they append the component's
suffix to the version and not the name before the version.
The latter causes problems when building against prebuilts and fixing
that causes the generated snapshot to be invalid because it contains
duplicate definitions of the "sdk_foo.stubs@current" module. One
explicitly in the Android.bp file and one created by the
"sdk_foo@current" module.
Removing the duplicates from the snapshot causes errors as the name
generated by the snapshot for the component module, i.e.
"sdk_foo.stubs@current" does not match the name generated by the
"sdk_foo@current", i.e. "sdk_foo@current.stubs".
This change fixes them together.
Bug: 179354495
Test: m nothing
Merged-In: I515f235fe21755b5275af12366e96c24c94c0273
Change-Id: I515f235fe21755b5275af12366e96c24c94c0273
(cherry picked from commit a1aa7387f74a49c8c974ba2198def0e081488624)
2021-04-29 22:50:40 +02:00
"foo.stubs" ,
2023-12-26 20:08:01 +01:00
"foo.stubs.exportable" ,
"foo.stubs.exportable.system" ,
"foo.stubs.exportable.test" ,
Remove duplicate component from sdk snapshot
Previously, an sdk snapshot could contain the following:
* A java_sdk_library_import module, e.g. "foo" which creates component
modules "foo.stubs", etc.
* A corresponding versioned module, e.g. "sdk_foo@current" which
created component modules "sdk_foo@current.stubs", etc.
* An internal (to the sdk snapshot) java_import for one of "foo"'s
components, e.g. "sdk_foo.stubs"
* A corresponding versioned module, e.g. "sdk_foo.stubs@current".
That causes a few problems:
1. The "foo.stubs" is duplicated.
2. The names of the components created by the versioned
java_sdk_library_import are invalid, as they append the component's
suffix to the version and not the name before the version.
The latter causes problems when building against prebuilts and fixing
that causes the generated snapshot to be invalid because it contains
duplicate definitions of the "sdk_foo.stubs@current" module. One
explicitly in the Android.bp file and one created by the
"sdk_foo@current" module.
Removing the duplicates from the snapshot causes errors as the name
generated by the snapshot for the component module, i.e.
"sdk_foo.stubs@current" does not match the name generated by the
"sdk_foo@current", i.e. "sdk_foo@current.stubs".
This change fixes them together.
Bug: 179354495
Test: m nothing
Merged-In: I515f235fe21755b5275af12366e96c24c94c0273
Change-Id: I515f235fe21755b5275af12366e96c24c94c0273
(cherry picked from commit a1aa7387f74a49c8c974ba2198def0e081488624)
2021-04-29 22:50:40 +02:00
"foo.stubs.source" ,
"foo.stubs.source.system" ,
"foo.stubs.source.test" ,
"foo.stubs.system" ,
"foo.stubs.test" ,
}
android . AssertArrayString ( t , "foo exported components" , expectedFooExportedComponents , exportedComponentsInfo . Components )
2021-06-01 22:18:08 +02:00
bazJavac := result . ModuleForTests ( "baz" , "android_common" ) . Rule ( "javac" )
// tests if baz is actually linked to the stubs lib
android . AssertStringDoesContain ( t , "baz javac classpath" , bazJavac . Args [ "classpath" ] , "foo.stubs.system.jar" )
// ... and not to the impl lib
android . AssertStringDoesNotContain ( t , "baz javac classpath" , bazJavac . Args [ "classpath" ] , "foo.jar" )
// test if baz is not linked to the system variant of foo
android . AssertStringDoesNotContain ( t , "baz javac classpath" , bazJavac . Args [ "classpath" ] , "foo.stubs.jar" )
bazTestJavac := result . ModuleForTests ( "baz-test" , "android_common" ) . Rule ( "javac" )
// tests if baz-test is actually linked to the test stubs lib
android . AssertStringDoesContain ( t , "baz-test javac classpath" , bazTestJavac . Args [ "classpath" ] , "foo.stubs.test.jar" )
baz29Javac := result . ModuleForTests ( "baz-29" , "android_common" ) . Rule ( "javac" )
// tests if baz-29 is actually linked to the system 29 stubs lib
android . AssertStringDoesContain ( t , "baz-29 javac classpath" , baz29Javac . Args [ "classpath" ] , "prebuilts/sdk/29/system/foo.jar" )
bazModule30Javac := result . ModuleForTests ( "baz-module-30" , "android_common" ) . Rule ( "javac" )
// tests if "baz-module-30" is actually linked to the module 30 stubs lib
android . AssertStringDoesContain ( t , "baz-module-30 javac classpath" , bazModule30Javac . Args [ "classpath" ] , "prebuilts/sdk/30/module-lib/foo.jar" )
// test if baz has exported SDK lib names foo and bar to qux
qux := result . ModuleForTests ( "qux" , "android_common" )
if quxLib , ok := qux . Module ( ) . ( * Library ) ; ok {
2021-08-12 17:16:11 +02:00
requiredSdkLibs , optionalSdkLibs := quxLib . ClassLoaderContexts ( ) . UsesLibs ( )
2021-08-18 17:57:11 +02:00
android . AssertDeepEquals ( t , "qux exports (required)" , [ ] string { "fred" , "quuz" , "foo" , "bar" } , requiredSdkLibs )
2021-08-12 17:16:11 +02:00
android . AssertDeepEquals ( t , "qux exports (optional)" , [ ] string { } , optionalSdkLibs )
2021-06-01 22:18:08 +02:00
}
2021-12-06 22:35:11 +01:00
2023-09-13 03:01:53 +02:00
// test if quuz have created the api_contribution module
result . ModuleForTests ( apiScopePublic . stubsSourceModuleName ( "quuz" ) + ".api.contribution" , "" )
2021-12-06 22:35:11 +01:00
fooDexJar := result . ModuleForTests ( "foo" , "android_common" ) . Rule ( "d8" )
// tests if kotlinc generated files are NOT excluded from output of foo.
android . AssertStringDoesNotContain ( t , "foo dex" , fooDexJar . BuildParams . Args [ "mergeZipsFlags" ] , "-stripFile META-INF/*.kotlin_module" )
barDexJar := result . ModuleForTests ( "bar" , "android_common" ) . Rule ( "d8" )
// tests if kotlinc generated files are excluded from output of bar.
android . AssertStringDoesContain ( t , "bar dex" , barDexJar . BuildParams . Args [ "mergeZipsFlags" ] , "-stripFile META-INF/*.kotlin_module" )
2021-06-01 22:18:08 +02:00
}
2021-09-07 19:21:59 +02:00
func TestJavaSdkLibrary_UpdatableLibrary ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"28" : { "foo" } ,
"29" : { "foo" } ,
"30" : { "foo" , "fooUpdatable" , "fooUpdatableErr" } ,
} ) ,
2021-09-28 17:40:23 +02:00
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
2021-12-22 16:28:05 +01:00
variables . Platform_version_active_codenames = [ ] string { "Tiramisu" , "U" , "V" , "W" , "X" }
2021-09-28 17:40:23 +02:00
} ) ,
2021-09-07 19:21:59 +02:00
) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "fooUpdatable" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
2021-09-28 17:40:23 +02:00
on_bootclasspath_since : "U" ,
on_bootclasspath_before : "V" ,
min_device_sdk : "W" ,
2021-12-22 16:28:05 +01:00
max_device_sdk : "X" ,
2021-09-28 17:40:23 +02:00
min_sdk_version : "S" ,
2021-09-07 19:21:59 +02:00
}
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
}
` )
2021-12-22 16:28:05 +01:00
2021-09-07 19:21:59 +02:00
// test that updatability attributes are passed on correctly
fooUpdatable := result . ModuleForTests ( "fooUpdatable.xml" , "android_common" ) . Rule ( "java_sdk_xml" )
2021-12-22 16:28:05 +01:00
android . AssertStringDoesContain ( t , "fooUpdatable.xml java_sdk_xml command" , fooUpdatable . RuleParams . Command , ` on-bootclasspath-since=\"U\" ` )
android . AssertStringDoesContain ( t , "fooUpdatable.xml java_sdk_xml command" , fooUpdatable . RuleParams . Command , ` on-bootclasspath-before=\"V\" ` )
android . AssertStringDoesContain ( t , "fooUpdatable.xml java_sdk_xml command" , fooUpdatable . RuleParams . Command , ` min-device-sdk=\"W\" ` )
android . AssertStringDoesContain ( t , "fooUpdatable.xml java_sdk_xml command" , fooUpdatable . RuleParams . Command , ` max-device-sdk=\"X\" ` )
2021-09-07 19:21:59 +02:00
// double check that updatability attributes are not written if they don't exist in the bp file
// the permissions file for the foo library defined above
fooPermissions := result . ModuleForTests ( "foo.xml" , "android_common" ) . Rule ( "java_sdk_xml" )
2021-10-29 11:32:32 +02:00
android . AssertStringDoesNotContain ( t , "foo.xml java_sdk_xml command" , fooPermissions . RuleParams . Command , ` on-bootclasspath-since ` )
android . AssertStringDoesNotContain ( t , "foo.xml java_sdk_xml command" , fooPermissions . RuleParams . Command , ` on-bootclasspath-before ` )
android . AssertStringDoesNotContain ( t , "foo.xml java_sdk_xml command" , fooPermissions . RuleParams . Command , ` min-device-sdk ` )
android . AssertStringDoesNotContain ( t , "foo.xml java_sdk_xml command" , fooPermissions . RuleParams . Command , ` max-device-sdk ` )
2021-09-07 19:21:59 +02:00
}
2021-09-28 17:40:23 +02:00
func TestJavaSdkLibrary_UpdatableLibrary_Validation_ValidVersion ( t * testing . T ) {
2021-09-07 19:21:59 +02:00
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"30" : { "fooUpdatable" , "fooUpdatableErr" } ,
} ) ,
) . ExtendWithErrorHandler ( android . FixtureExpectsAllErrorsToMatchAPattern (
[ ] string {
` on_bootclasspath_since: "aaa" could not be parsed as an integer and is not a recognized codename ` ,
` on_bootclasspath_before: "bbc" could not be parsed as an integer and is not a recognized codename ` ,
` min_device_sdk: "ccc" could not be parsed as an integer and is not a recognized codename ` ,
2021-12-22 16:28:05 +01:00
` max_device_sdk: "current" is not an allowed value for this attribute ` ,
2021-09-07 19:21:59 +02:00
} ) ) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "fooUpdatableErr" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
2021-09-28 17:40:23 +02:00
on_bootclasspath_since : "aaa" ,
on_bootclasspath_before : "bbc" ,
min_device_sdk : "ccc" ,
2021-12-22 16:28:05 +01:00
max_device_sdk : "current" ,
2021-09-28 17:40:23 +02:00
}
` )
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_AtLeastTAttributes ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"28" : { "foo" } ,
} ) ,
) . ExtendWithErrorHandler ( android . FixtureExpectsAllErrorsToMatchAPattern (
[ ] string {
"on_bootclasspath_since: Attribute value needs to be at least T" ,
"on_bootclasspath_before: Attribute value needs to be at least T" ,
"min_device_sdk: Attribute value needs to be at least T" ,
"max_device_sdk: Attribute value needs to be at least T" ,
} ,
) ) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
on_bootclasspath_since : "S" ,
on_bootclasspath_before : "S" ,
min_device_sdk : "S" ,
max_device_sdk : "S" ,
min_sdk_version : "S" ,
}
` )
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdk ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"28" : { "foo" } ,
} ) ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . Platform_version_active_codenames = [ ] string { "Tiramisu" , "U" , "V" }
} ) ,
) . ExtendWithErrorHandler ( android . FixtureExpectsAllErrorsToMatchAPattern (
[ ] string {
"min_device_sdk can't be greater than max_device_sdk" ,
} ,
) ) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
min_device_sdk : "V" ,
max_device_sdk : "U" ,
min_sdk_version : "S" ,
}
` )
}
func TestJavaSdkLibrary_UpdatableLibrary_Validation_MinAndMaxDeviceSdkAndModuleMinSdk ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"28" : { "foo" } ,
} ) ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . Platform_version_active_codenames = [ ] string { "Tiramisu" , "U" , "V" }
} ) ,
) . ExtendWithErrorHandler ( android . FixtureExpectsAllErrorsToMatchAPattern (
[ ] string {
regexp . QuoteMeta ( "min_device_sdk: Can't be less than module's min sdk (V)" ) ,
regexp . QuoteMeta ( "max_device_sdk: Can't be less than module's min sdk (V)" ) ,
} ,
) ) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
min_device_sdk : "U" ,
max_device_sdk : "U" ,
min_sdk_version : "V" ,
}
` )
}
func TestJavaSdkLibrary_UpdatableLibrary_usesNewTag ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"30" : { "foo" } ,
} ) ,
) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
min_device_sdk : "Tiramisu" ,
min_sdk_version : "S" ,
2021-09-07 19:21:59 +02:00
}
` )
2021-09-28 17:40:23 +02:00
// test that updatability attributes are passed on correctly
fooUpdatable := result . ModuleForTests ( "foo.xml" , "android_common" ) . Rule ( "java_sdk_xml" )
2021-12-22 20:53:01 +01:00
android . AssertStringDoesContain ( t , "foo.xml java_sdk_xml command" , fooUpdatable . RuleParams . Command , ` <apex-library ` )
2021-09-28 17:40:23 +02:00
android . AssertStringDoesNotContain ( t , "foo.xml java_sdk_xml command" , fooUpdatable . RuleParams . Command , ` <library ` )
2021-09-07 19:21:59 +02:00
}
2021-06-01 22:18:08 +02:00
func TestJavaSdkLibrary_StubOrImplOnlyLibs ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
libs : [ "lib" ] ,
static_libs : [ "static-lib" ] ,
impl_only_libs : [ "impl-only-lib" ] ,
stub_only_libs : [ "stub-only-lib" ] ,
stub_only_static_libs : [ "stub-only-static-lib" ] ,
}
java_defaults {
name : "defaults" ,
srcs : [ "a.java" ] ,
sdk_version : "current" ,
}
java_library { name : "lib" , defaults : [ "defaults" ] }
java_library { name : "static-lib" , defaults : [ "defaults" ] }
java_library { name : "impl-only-lib" , defaults : [ "defaults" ] }
java_library { name : "stub-only-lib" , defaults : [ "defaults" ] }
java_library { name : "stub-only-static-lib" , defaults : [ "defaults" ] }
` )
var expectations = [ ] struct {
lib string
on_impl_classpath bool
on_stub_classpath bool
in_impl_combined bool
in_stub_combined bool
} {
{ lib : "lib" , on_impl_classpath : true } ,
{ lib : "static-lib" , in_impl_combined : true } ,
{ lib : "impl-only-lib" , on_impl_classpath : true } ,
{ lib : "stub-only-lib" , on_stub_classpath : true } ,
{ lib : "stub-only-static-lib" , in_stub_combined : true } ,
}
verify := func ( sdklib , dep string , cp , combined bool ) {
sdklibCp := result . ModuleForTests ( sdklib , "android_common" ) . Rule ( "javac" ) . Args [ "classpath" ]
expected := cp || combined // Every combined jar is also on the classpath.
android . AssertStringContainsEquals ( t , "bad classpath for " + sdklib , sdklibCp , "/" + dep + ".jar" , expected )
combineJarInputs := result . ModuleForTests ( sdklib , "android_common" ) . Rule ( "combineJar" ) . Inputs . Strings ( )
depPath := filepath . Join ( "out" , "soong" , ".intermediates" , dep , "android_common" , "turbine-combined" , dep + ".jar" )
android . AssertStringListContainsEquals ( t , "bad combined inputs for " + sdklib , combineJarInputs , depPath , combined )
}
for _ , expectation := range expectations {
verify ( "sdklib.impl" , expectation . lib , expectation . on_impl_classpath , expectation . in_impl_combined )
2023-06-09 01:25:57 +02:00
stubName := apiScopePublic . sourceStubLibraryModuleName ( "sdklib" )
2021-06-01 22:18:08 +02:00
verify ( stubName , expectation . lib , expectation . on_stub_classpath , expectation . in_stub_combined )
}
}
func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
api_only : true ,
public : {
enabled : true ,
} ,
}
java_library {
name : "bar" ,
srcs : [ "b.java" ] ,
libs : [ "foo" ] ,
}
` )
// The bar library should depend on the stubs jar.
barLibrary := result . ModuleForTests ( "bar" , "android_common" ) . Rule ( "javac" )
if expected , actual := ` ^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$ ` , barLibrary . Args [ "classpath" ] ; ! regexp . MustCompile ( expected ) . MatchString ( actual ) {
t . Errorf ( "expected %q, found %#q" , expected , actual )
}
}
2021-09-21 16:25:12 +02:00
func TestJavaSdkLibrary_AccessOutputFiles ( t * testing . T ) {
2021-06-01 22:18:08 +02:00
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
2021-09-21 16:25:12 +02:00
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
annotations_enabled : true ,
public : {
enabled : true ,
} ,
}
java_library {
name : "bar" ,
srcs : [ "b.java" , ":foo{.public.stubs.source}" ] ,
java_resources : [ ":foo{.public.annotations.zip}" ] ,
}
` )
}
func TestJavaSdkLibrary_AccessOutputFiles_NoAnnotations ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` module "bar" variant "android_common": path dependency ":foo { .public.annotations.zip}": annotations.zip not available for api scope public ` ) ) .
RunTestWithBp ( t , `
2021-06-01 22:18:08 +02:00
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
public : {
enabled : true ,
} ,
}
java_library {
name : "bar" ,
srcs : [ "b.java" , ":foo{.public.stubs.source}" ] ,
2021-09-21 16:25:12 +02:00
java_resources : [ ":foo{.public.annotations.zip}" ] ,
2021-06-01 22:18:08 +02:00
}
` )
}
func TestJavaSdkLibrary_AccessOutputFiles_MissingScope ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` "foo" does not provide api scope system ` ) ) .
RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
public : {
enabled : true ,
} ,
}
java_library {
name : "bar" ,
srcs : [ "b.java" , ":foo{.system.stubs.source}" ] ,
}
` )
}
func TestJavaSdkLibrary_Deps ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib" ) ,
2023-12-26 20:08:01 +01:00
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_HIDDEN_API_EXPORTABLE_STUBS" : "true" ,
}
} ) ,
2021-06-01 22:18:08 +02:00
) . RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
}
` )
CheckModuleDependencies ( t , result . TestContext , "sdklib" , "android_common" , [ ] string {
` dex2oatd ` ,
2024-03-20 22:29:39 +01:00
` sdklib-removed.api.combined.public.latest ` ,
` sdklib.api.combined.public.latest ` ,
2021-06-01 22:18:08 +02:00
` sdklib.impl ` ,
` sdklib.stubs ` ,
2023-12-26 20:08:01 +01:00
` sdklib.stubs.exportable ` ,
2021-06-01 22:18:08 +02:00
` sdklib.stubs.source ` ,
` sdklib.xml ` ,
} )
}
func TestJavaSdkLibraryImport_AccessOutputFiles ( t * testing . T ) {
prepareForJavaTest . RunTestWithBp ( t , `
java_sdk_library_import {
name : "foo" ,
public : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "api/current.txt" ,
removed_api : "api/removed.txt" ,
2021-09-21 16:25:12 +02:00
annotations : "x/annotations.zip" ,
2021-06-01 22:18:08 +02:00
} ,
}
java_library {
name : "bar" ,
srcs : [ ":foo{.public.stubs.source}" ] ,
java_resources : [
":foo{.public.api.txt}" ,
":foo{.public.removed-api.txt}" ,
2021-09-21 16:25:12 +02:00
":foo{.public.annotations.zip}" ,
2021-06-01 22:18:08 +02:00
] ,
}
` )
}
func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid ( t * testing . T ) {
bp := `
java_sdk_library_import {
name : "foo" ,
public : {
jars : [ "a.jar" ] ,
} ,
}
`
t . Run ( "stubs.source" , func ( t * testing . T ) {
prepareForJavaTest .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` stubs.source not available for api scope public ` ) ) .
RunTestWithBp ( t , bp + `
java_library {
name : "bar" ,
srcs : [ ":foo{.public.stubs.source}" ] ,
java_resources : [
":foo{.public.api.txt}" ,
":foo{.public.removed-api.txt}" ,
] ,
}
` )
} )
t . Run ( "api.txt" , func ( t * testing . T ) {
prepareForJavaTest .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` api.txt not available for api scope public ` ) ) .
RunTestWithBp ( t , bp + `
java_library {
name : "bar" ,
srcs : [ "a.java" ] ,
java_resources : [
":foo{.public.api.txt}" ,
] ,
}
` )
} )
t . Run ( "removed-api.txt" , func ( t * testing . T ) {
prepareForJavaTest .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` removed-api.txt not available for api scope public ` ) ) .
RunTestWithBp ( t , bp + `
java_library {
name : "bar" ,
srcs : [ "a.java" ] ,
java_resources : [
":foo{.public.removed-api.txt}" ,
] ,
}
` )
} )
}
func TestJavaSdkLibrary_InvalidScopes ( t * testing . T ) {
prepareForJavaTest .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` module "foo": enabled api scope "system" depends on disabled scope "public" ` ) ) .
RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
// Explicitly disable public to test the check that ensures the set of enabled
// scopes is consistent.
public : {
enabled : false ,
} ,
system : {
enabled : true ,
} ,
}
` )
}
func TestJavaSdkLibrary_SdkVersion_ForScope ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
sdk_version : "module_current" ,
} ,
}
` )
}
func TestJavaSdkLibrary_ModuleLib ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
} ,
module_lib : {
enabled : true ,
} ,
}
` )
}
func TestJavaSdkLibrary_SystemServer ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
} ,
system_server : {
enabled : true ,
} ,
}
` )
}
Allow sdk_version: "system_server_current" modules to access module-lib APIs
Previously, a java module with sdk_version: "system_server_current",
would only be able to access the system server or public API of a
java_sdk_library. This change allows it to access the system server,
module lib, system and public APIs in that order.
The apiScope structs define the characteristics of each of the
different API scopes used as required by the java_sdk_library. They are
organized into a hierarchy which is used for two different purposes.
The first purpose is to define an extension hierachy. If scope X
extends Y then X provides a superset of all API elements (classes,
fields, methods, etc) provided by Y. That is reflected in the fact that
the .txt file for X would be a delta on the .txt file for Y. So, system
extends public and so system_current.txt only contains additional API
elements to add to current.txt.
The second purpose is when a java_sdk_library/import is asked to
provide a specific API scope. e.g. a library that has:
sdk_version: "module_current"
will ask each of the SDK libraries it depends upon for a module-lib
API. However, not all of them will provide an API for that scope. In
that case it will find the closest suitable API scope.
Previously, it did that by traversing up the API extension until it
found an API scope that it did provide and return that. As
system_server_current extended the public API that meant that a library
which has:
sdk_version: "system_server_current"
would provide a system server API if available, and if not fall
straight back to public. That meant that the library could not access
system or module-lib APIs even though it is running in the system
server which should be able to access all APIs.
One way to fix this would have been to just have system server API
scope extend module-lib but that would have had a number of nasty
side effects:
* It would have created a significant overhead as every module that
provides a system server API would also have to provide a module-lib
and system API, along with their corresponding .txt files.
* Each existing java_sdk_library that provided a system server API
would need those .txt files created.
* Generating sdk snapshots for older releases would have been more
complicated.
* It would have confused developers.
All of that would be unnecessary because the system server API scope is
intended to be provided by libraries that are used solely by the system
server so there is no point in them providing anything other than a
system server API.
So, instead a separate access hierarchy was added which is the same as
the extension hierarchy for all existing scopes except for the
system server scope, which instead of just being able to access the
public API will be able to access the module-lib scope, which can in
turn access system and it can in turn access public.
That achieves what we want which is a library that is loaded into the
system server to be able to access all API scopes.
Bug: 204176972
Test: m nothing
Change-Id: I854df63fcaeba32afbc1eb0d1a501238022673d0
2022-09-30 19:11:41 +02:00
func TestJavaSdkLibrary_SystemServer_AccessToStubScopeLibs ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo-public" , "foo-system" , "foo-module-lib" , "foo-system-server" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo-public" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
public : {
enabled : true ,
} ,
}
java_sdk_library {
name : "foo-system" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
} ,
}
java_sdk_library {
name : "foo-module-lib" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
} ,
module_lib : {
enabled : true ,
} ,
}
java_sdk_library {
name : "foo-system-server" ,
srcs : [ "a.java" ] ,
api_packages : [ "foo" ] ,
system_server : {
enabled : true ,
} ,
}
java_library {
name : "bar" ,
srcs : [ "a.java" ] ,
libs : [ "foo-public" , "foo-system" , "foo-module-lib" , "foo-system-server" ] ,
sdk_version : "system_server_current" ,
}
` )
stubsPath := func ( name string , scope * apiScope ) string {
name = scope . stubsLibraryModuleName ( name )
return fmt . Sprintf ( "out/soong/.intermediates/%[1]s/android_common/turbine-combined/%[1]s.jar" , name )
}
// The bar library should depend on the highest (where system server is highest and public is
// lowest) API scopes provided by each of the foo-* modules. The highest API scope provided by the
// foo-<x> module is <x>.
barLibrary := result . ModuleForTests ( "bar" , "android_common" ) . Rule ( "javac" )
stubLibraries := [ ] string {
stubsPath ( "foo-public" , apiScopePublic ) ,
stubsPath ( "foo-system" , apiScopeSystem ) ,
stubsPath ( "foo-module-lib" , apiScopeModuleLib ) ,
stubsPath ( "foo-system-server" , apiScopeSystemServer ) ,
}
expectedPattern := fmt . Sprintf ( ` ^-classpath .*:\Q%s\E$ ` , strings . Join ( stubLibraries , ":" ) )
if expected , actual := expectedPattern , barLibrary . Args [ "classpath" ] ; ! regexp . MustCompile ( expected ) . MatchString ( actual ) {
t . Errorf ( "expected pattern %q to match %#q" , expected , actual )
}
}
2021-06-01 22:18:08 +02:00
func TestJavaSdkLibrary_MissingScope ( t * testing . T ) {
prepareForJavaTest .
ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` requires api scope module-lib from foo but it only has \[\] available ` ) ) .
RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
public : {
enabled : false ,
} ,
}
java_library {
name : "baz" ,
srcs : [ "a.java" ] ,
libs : [ "foo" ] ,
sdk_version : "module_current" ,
}
` )
}
func TestJavaSdkLibrary_FallbackScope ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
system : {
enabled : true ,
} ,
}
java_library {
name : "baz" ,
srcs : [ "a.java" ] ,
libs : [ "foo" ] ,
// foo does not have module-lib scope so it should fallback to system
sdk_version : "module_current" ,
}
` )
}
func TestJavaSdkLibrary_DefaultToStubs ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
system : {
enabled : true ,
} ,
default_to_stubs : true ,
}
java_library {
name : "baz" ,
srcs : [ "a.java" ] ,
libs : [ "foo" ] ,
// does not have sdk_version set, should fallback to module,
// which will then fallback to system because the module scope
// is not enabled.
}
` )
// The baz library should depend on the system stubs jar.
bazLibrary := result . ModuleForTests ( "baz" , "android_common" ) . Rule ( "javac" )
if expected , actual := ` ^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$ ` , bazLibrary . Args [ "classpath" ] ; ! regexp . MustCompile ( expected ) . MatchString ( actual ) {
t . Errorf ( "expected %q, found %#q" , expected , actual )
}
}
func TestJavaSdkLibraryImport ( t * testing . T ) {
result := prepareForJavaTest . RunTestWithBp ( t , `
java_library {
name : "foo" ,
srcs : [ "a.java" ] ,
libs : [ "sdklib" ] ,
sdk_version : "current" ,
}
java_library {
name : "foo.system" ,
srcs : [ "a.java" ] ,
libs : [ "sdklib" ] ,
sdk_version : "system_current" ,
}
java_library {
name : "foo.test" ,
srcs : [ "a.java" ] ,
libs : [ "sdklib" ] ,
sdk_version : "test_current" ,
}
java_sdk_library_import {
name : "sdklib" ,
public : {
jars : [ "a.jar" ] ,
} ,
system : {
jars : [ "b.jar" ] ,
} ,
test : {
jars : [ "c.jar" ] ,
stub_srcs : [ "c.java" ] ,
} ,
}
` )
for _ , scope := range [ ] string { "" , ".system" , ".test" } {
fooModule := result . ModuleForTests ( "foo" + scope , "android_common" )
javac := fooModule . Rule ( "javac" )
sdklibStubsJar := result . ModuleForTests ( "sdklib.stubs" + scope , "android_common" ) . Rule ( "combineJar" ) . Output
android . AssertStringDoesContain ( t , "foo classpath" , javac . Args [ "classpath" ] , sdklibStubsJar . String ( ) )
}
CheckModuleDependencies ( t , result . TestContext , "sdklib" , "android_common" , [ ] string {
2021-09-09 10:12:46 +02:00
` dex2oatd ` ,
2021-06-01 22:18:08 +02:00
` prebuilt_sdklib.stubs ` ,
` prebuilt_sdklib.stubs.source.test ` ,
` prebuilt_sdklib.stubs.system ` ,
` prebuilt_sdklib.stubs.test ` ,
} )
}
func TestJavaSdkLibraryImport_WithSource ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib" ) ,
2023-12-26 20:08:01 +01:00
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_HIDDEN_API_EXPORTABLE_STUBS" : "true" ,
}
} ) ,
2021-06-01 22:18:08 +02:00
) . RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
}
java_sdk_library_import {
name : "sdklib" ,
public : {
jars : [ "a.jar" ] ,
} ,
}
` )
CheckModuleDependencies ( t , result . TestContext , "sdklib" , "android_common" , [ ] string {
` dex2oatd ` ,
` prebuilt_sdklib ` ,
2024-03-20 22:29:39 +01:00
` sdklib-removed.api.combined.public.latest ` ,
` sdklib.api.combined.public.latest ` ,
2021-06-01 22:18:08 +02:00
` sdklib.impl ` ,
` sdklib.stubs ` ,
2023-12-26 20:08:01 +01:00
` sdklib.stubs.exportable ` ,
2021-06-01 22:18:08 +02:00
` sdklib.stubs.source ` ,
` sdklib.xml ` ,
} )
CheckModuleDependencies ( t , result . TestContext , "prebuilt_sdklib" , "android_common" , [ ] string {
2023-12-13 01:06:32 +01:00
` all_apex_contributions ` ,
2021-06-01 22:18:08 +02:00
` prebuilt_sdklib.stubs ` ,
` sdklib.impl ` ,
// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
// dependency is added after prebuilts may have been renamed and so has to use
// the renamed name.
` sdklib.xml ` ,
} )
}
2022-09-27 13:41:52 +02:00
func testJavaSdkLibraryImport_Preferred ( t * testing . T , prefer string , preparer android . FixturePreparer ) {
2021-06-01 22:18:08 +02:00
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib" ) ,
2022-09-27 13:41:52 +02:00
preparer ,
2023-12-26 20:08:01 +01:00
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_HIDDEN_API_EXPORTABLE_STUBS" : "true" ,
}
} ) ,
2021-06-01 22:18:08 +02:00
) . RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
}
java_sdk_library_import {
name : "sdklib" ,
2022-09-27 13:41:52 +02:00
` +prefer+ `
2021-06-01 22:18:08 +02:00
public : {
jars : [ "a.jar" ] ,
2022-09-27 13:41:52 +02:00
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
2021-06-01 22:18:08 +02:00
} ,
}
2022-09-27 13:41:52 +02:00
java_library {
name : "combined" ,
static_libs : [
"sdklib.stubs" ,
] ,
java_resources : [
":sdklib.stubs.source" ,
":sdklib{.public.api.txt}" ,
":sdklib{.public.removed-api.txt}" ,
":sdklib{.public.annotations.zip}" ,
] ,
sdk_version : "none" ,
system_modules : "none" ,
}
java_library {
name : "public" ,
srcs : [ "a.java" ] ,
libs : [ "sdklib" ] ,
sdk_version : "current" ,
}
2021-06-01 22:18:08 +02:00
` )
CheckModuleDependencies ( t , result . TestContext , "sdklib" , "android_common" , [ ] string {
` prebuilt_sdklib ` ,
2024-03-20 22:29:39 +01:00
` sdklib-removed.api.combined.public.latest ` ,
` sdklib.api.combined.public.latest ` ,
2021-06-01 22:18:08 +02:00
` sdklib.impl ` ,
` sdklib.stubs ` ,
2023-12-26 20:08:01 +01:00
` sdklib.stubs.exportable ` ,
2021-06-01 22:18:08 +02:00
` sdklib.stubs.source ` ,
` sdklib.xml ` ,
} )
CheckModuleDependencies ( t , result . TestContext , "prebuilt_sdklib" , "android_common" , [ ] string {
2023-12-13 01:06:32 +01:00
` all_apex_contributions ` ,
2021-09-09 10:12:46 +02:00
` dex2oatd ` ,
2021-06-01 22:18:08 +02:00
` prebuilt_sdklib.stubs ` ,
2022-09-27 13:41:52 +02:00
` prebuilt_sdklib.stubs.source ` ,
2021-06-01 22:18:08 +02:00
` sdklib.impl ` ,
` sdklib.xml ` ,
} )
2022-09-27 13:41:52 +02:00
// Make sure that dependencies on child modules use the prebuilt when preferred.
CheckModuleDependencies ( t , result . TestContext , "combined" , "android_common" , [ ] string {
// Each use of :sdklib{...} adds a dependency onto prebuilt_sdklib.
` prebuilt_sdklib ` ,
` prebuilt_sdklib ` ,
` prebuilt_sdklib ` ,
` prebuilt_sdklib.stubs ` ,
` prebuilt_sdklib.stubs.source ` ,
} )
// Make sure that dependencies on sdklib that resolve to one of the child libraries use the
// prebuilt library.
public := result . ModuleForTests ( "public" , "android_common" )
rule := public . Output ( "javac/public.jar" )
inputs := rule . Implicits . Strings ( )
expected := "out/soong/.intermediates/prebuilt_sdklib.stubs/android_common/combined/sdklib.stubs.jar"
if ! android . InList ( expected , inputs ) {
t . Errorf ( "expected %q to contain %q" , inputs , expected )
}
}
func TestJavaSdkLibraryImport_Preferred ( t * testing . T ) {
t . Run ( "prefer" , func ( t * testing . T ) {
testJavaSdkLibraryImport_Preferred ( t , "prefer: true," , android . NullFixturePreparer )
} )
t . Run ( "use_source_config_var" , func ( t * testing . T ) {
testJavaSdkLibraryImport_Preferred ( t ,
"use_source_config_var: {config_namespace: \"acme\", var_name: \"use_source\"}," ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . VendorVars = map [ string ] map [ string ] string {
"acme" : {
"use_source" : "false" ,
} ,
}
} ) )
} )
2021-06-01 22:18:08 +02:00
}
2023-10-27 22:06:32 +02:00
// If a module is listed in `mainline_module_contributions, it should be used
// It will supersede any other source vs prebuilt selection mechanism like `prefer` attribute
func TestSdkLibraryImport_MetadataModuleSupersedesPreferred ( t * testing . T ) {
bp := `
apex_contributions {
name : "my_mainline_module_contributions" ,
api_domain : "my_mainline_module" ,
contents : [
// legacy mechanism prefers the prebuilt
// mainline_module_contributions supersedes this since source is listed explicitly
"sdklib.prebuilt_preferred_using_legacy_flags" ,
// legacy mechanism prefers the source
// mainline_module_contributions supersedes this since prebuilt is listed explicitly
"prebuilt_sdklib.source_preferred_using_legacy_flags" ,
] ,
}
java_sdk_library {
name : "sdklib.prebuilt_preferred_using_legacy_flags" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
system : {
enabled : true ,
}
}
java_sdk_library_import {
name : "sdklib.prebuilt_preferred_using_legacy_flags" ,
prefer : true , // prebuilt is preferred using legacy mechanism
public : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
system : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
}
java_sdk_library {
name : "sdklib.source_preferred_using_legacy_flags" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
system : {
enabled : true ,
}
}
java_sdk_library_import {
name : "sdklib.source_preferred_using_legacy_flags" ,
prefer : false , // source is preferred using legacy mechanism
public : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
system : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
}
// rdeps
java_library {
name : "public" ,
srcs : [ "a.java" ] ,
libs : [
// this should get source since source is listed in my_mainline_module_contributions
"sdklib.prebuilt_preferred_using_legacy_flags.stubs" ,
"sdklib.prebuilt_preferred_using_legacy_flags.stubs.system" ,
// this should get prebuilt since source is listed in my_mainline_module_contributions
"sdklib.source_preferred_using_legacy_flags.stubs" ,
"sdklib.source_preferred_using_legacy_flags.stubs.system" ,
] ,
}
`
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib.source_preferred_using_legacy_flags" , "sdklib.prebuilt_preferred_using_legacy_flags" ) ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES" : "my_mainline_module_contributions" ,
}
} ) ,
) . RunTestWithBp ( t , bp )
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
public := result . ModuleForTests ( "public" , "android_common" )
rule := public . Output ( "javac/public.jar" )
inputs := rule . Implicits . Strings ( )
expectedInputs := [ ] string {
// source
"out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.jar" ,
"out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.jar" ,
// prebuilt
"out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.jar" ,
"out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs.system/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.system.jar" ,
}
for _ , expected := range expectedInputs {
if ! android . InList ( expected , inputs ) {
t . Errorf ( "expected %q to contain %q" , inputs , expected )
}
}
}
2021-06-01 22:18:08 +02:00
func TestJavaSdkLibraryEnforce ( t * testing . T ) {
partitionToBpOption := func ( partition string ) string {
switch partition {
case "system" :
return ""
case "vendor" :
return "soc_specific: true,"
case "product" :
return "product_specific: true,"
default :
panic ( "Invalid partition group name: " + partition )
}
}
type testConfigInfo struct {
libraryType string
fromPartition string
toPartition string
enforceVendorInterface bool
enforceProductInterface bool
enforceJavaSdkLibraryCheck bool
allowList [ ] string
}
createPreparer := func ( info testConfigInfo ) android . FixturePreparer {
bpFileTemplate := `
java_library {
name : "foo" ,
srcs : [ "foo.java" ] ,
libs : [ "bar" ] ,
sdk_version : "current" ,
% s
}
% s {
name : "bar" ,
srcs : [ "bar.java" ] ,
sdk_version : "current" ,
% s
}
`
bpFile := fmt . Sprintf ( bpFileTemplate ,
partitionToBpOption ( info . fromPartition ) ,
info . libraryType ,
partitionToBpOption ( info . toPartition ) )
return android . GroupFixturePreparers (
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "bar" ) ,
android . FixtureWithRootAndroidBp ( bpFile ) ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . EnforceProductPartitionInterface = proptools . BoolPtr ( info . enforceProductInterface )
if info . enforceVendorInterface {
variables . DeviceVndkVersion = proptools . StringPtr ( "current" )
}
variables . EnforceInterPartitionJavaSdkLibrary = proptools . BoolPtr ( info . enforceJavaSdkLibraryCheck )
variables . InterPartitionJavaLibraryAllowList = info . allowList
} ) ,
)
}
runTest := func ( t * testing . T , info testConfigInfo , expectedErrorPattern string ) {
t . Run ( fmt . Sprintf ( "%v" , info ) , func ( t * testing . T ) {
errorHandler := android . FixtureExpectsNoErrors
if expectedErrorPattern != "" {
errorHandler = android . FixtureExpectsAtLeastOneErrorMatchingPattern ( expectedErrorPattern )
}
android . GroupFixturePreparers (
prepareForJavaTest ,
createPreparer ( info ) ,
) .
ExtendWithErrorHandler ( errorHandler ) .
RunTest ( t )
} )
}
errorMessage := "is not allowed across the partitions"
runTest ( t , testConfigInfo {
libraryType : "java_library" ,
fromPartition : "product" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : false ,
} , "" )
runTest ( t , testConfigInfo {
libraryType : "java_library" ,
fromPartition : "product" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : false ,
enforceJavaSdkLibraryCheck : true ,
} , "" )
runTest ( t , testConfigInfo {
libraryType : "java_library" ,
fromPartition : "product" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
} , errorMessage )
runTest ( t , testConfigInfo {
libraryType : "java_library" ,
fromPartition : "vendor" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
} , errorMessage )
runTest ( t , testConfigInfo {
libraryType : "java_library" ,
fromPartition : "vendor" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
allowList : [ ] string { "bar" } ,
} , "" )
runTest ( t , testConfigInfo {
libraryType : "java_library" ,
fromPartition : "vendor" ,
toPartition : "product" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
} , errorMessage )
runTest ( t , testConfigInfo {
libraryType : "java_sdk_library" ,
fromPartition : "product" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
} , "" )
runTest ( t , testConfigInfo {
libraryType : "java_sdk_library" ,
fromPartition : "vendor" ,
toPartition : "system" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
} , "" )
runTest ( t , testConfigInfo {
libraryType : "java_sdk_library" ,
fromPartition : "vendor" ,
toPartition : "product" ,
enforceVendorInterface : true ,
enforceProductInterface : true ,
enforceJavaSdkLibraryCheck : true ,
} , "" )
}
2021-06-01 22:39:09 +02:00
func TestJavaSdkLibraryDist ( t * testing . T ) {
result := android . GroupFixturePreparers (
PrepareForTestWithJavaBuildComponents ,
PrepareForTestWithJavaDefaultModules ,
PrepareForTestWithJavaSdkLibraryFiles ,
2021-06-02 22:02:51 +02:00
FixtureWithLastReleaseApis (
"sdklib_no_group" ,
"sdklib_group_foo" ,
"sdklib_owner_foo" ,
"foo" ) ,
2024-03-20 01:44:54 +01:00
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_HIDDEN_API_EXPORTABLE_STUBS" : "true" ,
}
} ) ,
2021-06-01 22:39:09 +02:00
) . RunTestWithBp ( t , `
java_sdk_library {
2021-06-01 23:07:56 +02:00
name : "sdklib_no_group" ,
2021-06-01 22:39:09 +02:00
srcs : [ "foo.java" ] ,
}
2021-06-01 22:13:40 +02:00
java_sdk_library {
name : "sdklib_group_foo" ,
srcs : [ "foo.java" ] ,
dist_group : "foo" ,
}
2021-06-01 22:39:09 +02:00
java_sdk_library {
name : "sdklib_owner_foo" ,
srcs : [ "foo.java" ] ,
owner : "foo" ,
}
java_sdk_library {
name : "sdklib_stem_foo" ,
srcs : [ "foo.java" ] ,
dist_stem : "foo" ,
}
` )
type testCase struct {
module string
distDir string
distStem string
}
testCases := [ ] testCase {
{
2021-06-01 23:07:56 +02:00
module : "sdklib_no_group" ,
2021-06-01 23:05:09 +02:00
distDir : "apistubs/unknown/public" ,
2021-06-01 23:07:56 +02:00
distStem : "sdklib_no_group.jar" ,
2021-06-01 22:39:09 +02:00
} ,
2021-06-01 22:13:40 +02:00
{
module : "sdklib_group_foo" ,
distDir : "apistubs/foo/public" ,
distStem : "sdklib_group_foo.jar" ,
} ,
2021-06-01 22:39:09 +02:00
{
2021-06-01 23:07:56 +02:00
// Owner doesn't affect distDir after b/186723288.
2021-06-01 22:39:09 +02:00
module : "sdklib_owner_foo" ,
2021-06-01 23:07:56 +02:00
distDir : "apistubs/unknown/public" ,
2021-06-01 22:39:09 +02:00
distStem : "sdklib_owner_foo.jar" ,
} ,
{
module : "sdklib_stem_foo" ,
2021-06-01 23:05:09 +02:00
distDir : "apistubs/unknown/public" ,
2021-06-01 22:39:09 +02:00
distStem : "foo.jar" ,
} ,
}
for _ , tt := range testCases {
t . Run ( tt . module , func ( t * testing . T ) {
2023-12-20 03:53:38 +01:00
m := result . ModuleForTests ( apiScopePublic . exportableStubsLibraryModuleName ( tt . module ) , "android_common" ) . Module ( ) . ( * Library )
2021-06-01 22:39:09 +02:00
dists := m . Dists ( )
if len ( dists ) != 1 {
t . Fatalf ( "expected exactly 1 dist entry, got %d" , len ( dists ) )
}
if g , w := String ( dists [ 0 ] . Dir ) , tt . distDir ; g != w {
t . Errorf ( "expected dist dir %q, got %q" , w , g )
}
if g , w := String ( dists [ 0 ] . Dest ) , tt . distStem ; g != w {
t . Errorf ( "expected dist stem %q, got %q" , w , g )
}
} )
}
}
2021-12-06 12:40:46 +01:00
func TestSdkLibrary_CheckMinSdkVersion ( t * testing . T ) {
preparer := android . GroupFixturePreparers (
PrepareForTestWithJavaBuildComponents ,
PrepareForTestWithJavaDefaultModules ,
PrepareForTestWithJavaSdkLibraryFiles ,
)
preparer . RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
static_libs : [ "util" ] ,
min_sdk_version : "30" ,
unsafe_ignore_missing_latest_api : true ,
}
java_library {
name : "util" ,
srcs : [ "a.java" ] ,
min_sdk_version : "30" ,
}
` )
preparer .
RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
libs : [ "util" ] ,
impl_only_libs : [ "util" ] ,
stub_only_libs : [ "util" ] ,
stub_only_static_libs : [ "util" ] ,
min_sdk_version : "30" ,
unsafe_ignore_missing_latest_api : true ,
}
java_library {
name : "util" ,
srcs : [ "a.java" ] ,
}
` )
preparer . ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` module "util".*should support min_sdk_version\(30\) ` ) ) .
RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
static_libs : [ "util" ] ,
min_sdk_version : "30" ,
unsafe_ignore_missing_latest_api : true ,
}
java_library {
name : "util" ,
srcs : [ "a.java" ] ,
min_sdk_version : "31" ,
}
` )
preparer . ExtendWithErrorHandler ( android . FixtureExpectsAtLeastOneErrorMatchingPattern ( ` module "another_util".*should support min_sdk_version\(30\) ` ) ) .
RunTestWithBp ( t , `
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
static_libs : [ "util" ] ,
min_sdk_version : "30" ,
unsafe_ignore_missing_latest_api : true ,
}
java_library {
name : "util" ,
srcs : [ "a.java" ] ,
static_libs : [ "another_util" ] ,
min_sdk_version : "30" ,
}
java_library {
name : "another_util" ,
srcs : [ "a.java" ] ,
min_sdk_version : "31" ,
}
` )
}
2022-11-21 13:38:25 +01:00
func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
public : {
enabled : true ,
} ,
stub_only_libs : [ "bar-lib" ] ,
}
java_library {
name : "bar-lib" ,
2023-08-10 02:07:03 +02:00
srcs : [ "b.java" ] ,
}
` )
// The foo.stubs.source should depend on bar-lib
fooStubsSources := result . ModuleForTests ( "foo.stubs.source" , "android_common" ) . Module ( ) . ( * Droidstubs )
android . AssertStringListContains ( t , "foo stubs should depend on bar-lib" , fooStubsSources . Javadoc . properties . Libs , "bar-lib" )
}
func TestJavaSdkLibrary_Scope_Libs_PassedToDroidstubs ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" ] ,
public : {
enabled : true ,
libs : [ "bar-lib" ] ,
} ,
}
java_library {
name : "bar-lib" ,
2022-11-21 13:38:25 +01:00
srcs : [ "b.java" ] ,
}
` )
// The foo.stubs.source should depend on bar-lib
fooStubsSources := result . ModuleForTests ( "foo.stubs.source" , "android_common" ) . Module ( ) . ( * Droidstubs )
android . AssertStringListContains ( t , "foo stubs should depend on bar-lib" , fooStubsSources . Javadoc . properties . Libs , "bar-lib" )
}
2023-03-23 18:44:51 +01:00
func TestJavaSdkLibrary_ApiLibrary ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
android . FixtureModifyConfig ( func ( config android . Config ) {
config . SetApiLibraries ( [ ] string { "foo" } )
} ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
} ,
module_lib : {
enabled : true ,
} ,
test : {
enabled : true ,
} ,
}
` )
testCases := [ ] struct {
2023-06-23 01:13:51 +02:00
scope * apiScope
apiContributions [ ] string
fullApiSurfaceStub string
2023-03-23 18:44:51 +01:00
} {
{
2023-06-23 01:13:51 +02:00
scope : apiScopePublic ,
apiContributions : [ ] string { "foo.stubs.source.api.contribution" } ,
2023-07-25 07:51:46 +02:00
fullApiSurfaceStub : "android_stubs_current" ,
2023-03-23 18:44:51 +01:00
} ,
{
2023-06-23 01:13:51 +02:00
scope : apiScopeSystem ,
apiContributions : [ ] string { "foo.stubs.source.system.api.contribution" , "foo.stubs.source.api.contribution" } ,
2023-07-25 07:51:46 +02:00
fullApiSurfaceStub : "android_system_stubs_current" ,
2023-03-23 18:44:51 +01:00
} ,
{
2023-06-23 01:13:51 +02:00
scope : apiScopeTest ,
apiContributions : [ ] string { "foo.stubs.source.test.api.contribution" , "foo.stubs.source.system.api.contribution" , "foo.stubs.source.api.contribution" } ,
2023-07-25 07:51:46 +02:00
fullApiSurfaceStub : "android_test_stubs_current" ,
2023-03-23 18:44:51 +01:00
} ,
{
2023-06-23 01:13:51 +02:00
scope : apiScopeModuleLib ,
apiContributions : [ ] string { "foo.stubs.source.module_lib.api.contribution" , "foo.stubs.source.system.api.contribution" , "foo.stubs.source.api.contribution" } ,
fullApiSurfaceStub : "android_module_lib_stubs_current_full.from-text" ,
2023-03-23 18:44:51 +01:00
} ,
}
for _ , c := range testCases {
m := result . ModuleForTests ( c . scope . apiLibraryModuleName ( "foo" ) , "android_common" ) . Module ( ) . ( * ApiLibrary )
android . AssertArrayString ( t , "Module expected to contain api contributions" , c . apiContributions , m . properties . Api_contributions )
2023-06-23 01:13:51 +02:00
android . AssertStringEquals ( t , "Module expected to contain full api surface api library" , c . fullApiSurfaceStub , * m . properties . Full_api_surface_stub )
2023-03-23 18:44:51 +01:00
}
}
2023-09-07 03:18:31 +02:00
func TestStaticDepStubLibrariesVisibility ( t * testing . T ) {
android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
android . FixtureMergeMockFs (
map [ string ] [ ] byte {
"A.java" : nil ,
"dir/Android.bp" : [ ] byte (
`
java_library {
name : "bar" ,
srcs : [ "A.java" ] ,
libs : [ "foo.stubs.from-source" ] ,
}
` ) ,
"dir/A.java" : nil ,
} ,
) . ExtendWithErrorHandler (
android . FixtureExpectsAtLeastOneErrorMatchingPattern (
` module "bar" variant "android_common": depends on //.:foo.stubs.from-source which is not visible to this module ` ) ) ,
) . RunTestWithBp ( t , `
java_sdk_library {
name : "foo" ,
srcs : [ "A.java" ] ,
}
` )
}
Add the ability for a java_sdk_library to depend on another.
This simply exports all of the uses_libs: [] libraries into a
"dependency=''" statement in the generated XML file (with the <library>
stanza in it).
Test: `go test` in java/
Bug: 184396657
NOTE FOR REVIEWERS - original patch and result patch are not identical.
PLEASE REVIEW CAREFULLY.
Diffs between the patches:
func formattedDependenciesAttribute(dependencies []string) string {
> + if dependencies == nil {
> + return ""
> + }
> + return fmt.Sprintf(` dependency=\"%s\"\n`, strings.Join(dependencies, ":"))
> +}
> +
> + dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
> + dependenciesAttr,
> --- java/sdk_library_test.go
> +++ java/sdk_library_test.go
> +
> +func TestSdkLibraryDependency(t *testing.T) {
> + result := android.GroupFixturePreparers(
> + prepareForJavaTest,
> + PrepareForTestWithJavaSdkLibraryFiles,
> + FixtureWithPrebuiltApis(map[string][]string{
> + "30": {"bar", "foo"},
> + }),
> + ).RunTestWithBp(t,
> + `
> + java_sdk_library {
> + name: "foo",
> + srcs: ["a.java", "b.java"],
> + api_packages: ["foo"],
> + }
> +
> + java_sdk_library {
> + name: "bar",
> + srcs: ["c.java", "b.java"],
> + libs: [
> + "foo",
> + ],
> + uses_libs: [
> + "foo",
> + ],
> + }
> +`)
> +
> + barPermissions := result.ModuleForTests("bar.xml", "android_common").Rule("java_sdk_xml")
> +
> + android.AssertStringDoesContain(t, "bar.xml java_sdk_xml command", barPermissions.RuleParams.Command, `dependency=\"foo\"`)
> +}
Original patch:
diff --git a/java/sdk_library.go b/java/sdk_library.go
old mode 100644
new mode 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1993,6 +1993,7 @@
Min_device_sdk *string
Max_device_sdk *string
Sdk_library_min_api_level *string
+ Uses_libs_dependencies []string
}{
Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Lib_name: proptools.StringPtr(module.BaseModuleName()),
@@ -2002,6 +2003,7 @@
Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
Sdk_library_min_api_level: &moduleMinApiLevelStr,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -2968,6 +2970,11 @@
//
// This value comes from the ApiLevel of the MinSdkVersion property.
Sdk_library_min_api_level *string
+
+ // Uses-libs dependencies that the shared libra
[[[Original patch trimmed due to size. Decoded string size: 3559. Decoded string SHA1: 67fbd040aa818732a686514c4556850c8c36dc8d.]]]
Result patch:
diff --git a/java/sdk_library.go b/java/sdk_library.go
index fb27812..fbfe509 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1993,6 +1993,7 @@
Min_device_sdk *string
Max_device_sdk *string
Sdk_library_min_api_level *string
+ Uses_libs_dependencies []string
}{
Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Lib_name: proptools.StringPtr(module.BaseModuleName()),
@@ -2002,6 +2003,7 @@
Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
Sdk_library_min_api_level: &moduleMinApiLevelStr,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -2968,6 +2970,11 @@
//
// This value comes from the ApiLevel of the MinSdkVersion property.
Sdk_library_min_api_level *string
+
+ // Uses-libs dependencies that the shared library
[[[Result patch trimmed due to size. Decoded string size: 3614. Decoded string SHA1: b5730ecbeeaad420439ddb67eaaa9150ede94585.]]]
Change-Id: I73f69e2a4573e416492f68e083fe739f3f75b721
2023-11-27 13:07:36 +01:00
func TestSdkLibraryDependency ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithPrebuiltApis ( map [ string ] [ ] string {
"30" : { "bar" , "foo" } ,
} ) ,
) . RunTestWithBp ( t ,
`
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
}
java_sdk_library {
name : "bar" ,
srcs : [ "c.java" , "b.java" ] ,
libs : [
"foo" ,
] ,
uses_libs : [
"foo" ,
] ,
}
` )
barPermissions := result . ModuleForTests ( "bar.xml" , "android_common" ) . Rule ( "java_sdk_xml" )
android . AssertStringDoesContain ( t , "bar.xml java_sdk_xml command" , barPermissions . RuleParams . Command , ` dependency=\"foo\" ` )
}
2023-12-20 03:53:38 +01:00
func TestSdkLibraryExportableStubsLibrary ( t * testing . T ) {
result := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "foo" ) ,
android . FixtureModifyConfig ( func ( config android . Config ) {
config . SetApiLibraries ( [ ] string { "foo" } )
} ) ,
) . RunTestWithBp ( t , `
aconfig_declarations {
name : "bar" ,
package : "com.example.package" ,
srcs : [
"bar.aconfig" ,
] ,
}
java_sdk_library {
name : "foo" ,
srcs : [ "a.java" , "b.java" ] ,
api_packages : [ "foo" ] ,
system : {
enabled : true ,
} ,
module_lib : {
enabled : true ,
} ,
test : {
enabled : true ,
} ,
aconfig_declarations : [
"bar" ,
] ,
}
` )
exportableStubsLibraryModuleName := apiScopePublic . exportableStubsLibraryModuleName ( "foo" )
exportableSourceStubsLibraryModuleName := apiScopePublic . exportableSourceStubsLibraryModuleName ( "foo" )
// Check modules generation
topLevelModule := result . ModuleForTests ( exportableStubsLibraryModuleName , "android_common" )
result . ModuleForTests ( exportableSourceStubsLibraryModuleName , "android_common" )
// Check static lib dependency
android . AssertBoolEquals ( t , "exportable top level stubs library module depends on the" +
"exportable source stubs library module" , true ,
CheckModuleHasDependency ( t , result . TestContext , exportableStubsLibraryModuleName ,
"android_common" , exportableSourceStubsLibraryModuleName ) ,
)
android . AssertArrayString ( t , "exportable source stub library is a static lib of the" +
"top level exportable stubs library" , [ ] string { exportableSourceStubsLibraryModuleName } ,
topLevelModule . Module ( ) . ( * Library ) . properties . Static_libs )
}
2024-02-02 00:41:11 +01:00
// For java libraries depending on java_sdk_library(_import) via libs, assert that
// rdep gets stubs of source if source is listed in apex_contributions and prebuilt has prefer (legacy mechanism)
func TestStubResolutionOfJavaSdkLibraryInLibs ( t * testing . T ) {
bp := `
apex_contributions {
name : "my_mainline_module_contributions" ,
api_domain : "my_mainline_module" ,
contents : [ "sdklib" ] , // source is selected using apex_contributions, but prebuilt is selected using prefer
}
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
}
java_sdk_library_import {
name : "sdklib" ,
public : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
prefer : true , // Set prefer explicitly on the prebuilt. We will assert that rdep gets source in a test case.
}
// rdeps
java_library {
name : "mymodule" ,
srcs : [ "a.java" ] ,
sdk_version : "current" ,
libs : [ "sdklib" , ] , // this should be dynamically resolved to sdklib.stubs (source) or prebuilt_sdklib.stubs (prebuilt)
}
`
fixture := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib" ) ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
// We can use any of the apex contribution build flags from build/soong/android/config.go#mainlineApexContributionBuildFlags here
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES" : "my_mainline_module_contributions" ,
}
} ) ,
)
result := fixture . RunTestWithBp ( t , bp )
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
public := result . ModuleForTests ( "mymodule" , "android_common" )
rule := public . Output ( "javac/mymodule.jar" )
inputs := rule . Implicits . Strings ( )
android . AssertStringListContains ( t , "Could not find the expected stub on classpath" , inputs , "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar" )
}
2024-01-19 01:22:22 +01:00
// test that rdep gets resolved to the correct version of a java_sdk_library (source or a specific prebuilt)
func TestMultipleSdkLibraryPrebuilts ( t * testing . T ) {
bp := `
apex_contributions {
name : "my_mainline_module_contributions" ,
api_domain : "my_mainline_module" ,
contents : [ "%s" ] ,
}
java_sdk_library {
name : "sdklib" ,
srcs : [ "a.java" ] ,
sdk_version : "none" ,
system_modules : "none" ,
public : {
enabled : true ,
} ,
}
java_sdk_library_import {
name : "sdklib.v1" , //prebuilt
source_module_name : "sdklib" ,
public : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
}
java_sdk_library_import {
name : "sdklib.v2" , //prebuilt
source_module_name : "sdklib" ,
public : {
jars : [ "a.jar" ] ,
stub_srcs : [ "a.java" ] ,
current_api : "current.txt" ,
removed_api : "removed.txt" ,
annotations : "annotations.zip" ,
} ,
}
// rdeps
java_library {
name : "mymodule" ,
srcs : [ "a.java" ] ,
libs : [ "sdklib.stubs" , ] ,
}
`
testCases := [ ] struct {
desc string
selectedDependencyName string
expectedStubPath string
} {
{
desc : "Source library is selected using apex_contributions" ,
selectedDependencyName : "sdklib" ,
expectedStubPath : "out/soong/.intermediates/sdklib.stubs/android_common/turbine-combined/sdklib.stubs.jar" ,
} ,
{
desc : "Prebuilt library v1 is selected using apex_contributions" ,
selectedDependencyName : "prebuilt_sdklib.v1" ,
expectedStubPath : "out/soong/.intermediates/prebuilt_sdklib.v1.stubs/android_common/combined/sdklib.stubs.jar" ,
} ,
{
desc : "Prebuilt library v2 is selected using apex_contributions" ,
selectedDependencyName : "prebuilt_sdklib.v2" ,
expectedStubPath : "out/soong/.intermediates/prebuilt_sdklib.v2.stubs/android_common/combined/sdklib.stubs.jar" ,
} ,
}
fixture := android . GroupFixturePreparers (
prepareForJavaTest ,
PrepareForTestWithJavaSdkLibraryFiles ,
FixtureWithLastReleaseApis ( "sdklib" , "sdklib.v1" , "sdklib.v2" ) ,
android . FixtureModifyProductVariables ( func ( variables android . FixtureProductVariables ) {
variables . BuildFlags = map [ string ] string {
"RELEASE_APEX_CONTRIBUTIONS_ADSERVICES" : "my_mainline_module_contributions" ,
}
} ) ,
)
for _ , tc := range testCases {
result := fixture . RunTestWithBp ( t , fmt . Sprintf ( bp , tc . selectedDependencyName ) )
// Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
public := result . ModuleForTests ( "mymodule" , "android_common" )
rule := public . Output ( "javac/mymodule.jar" )
inputs := rule . Implicits . Strings ( )
android . AssertStringListContains ( t , "Could not find the expected stub on classpath" , inputs , tc . expectedStubPath )
}
}