platform_build_soong/sdk/sdk_test.go

467 lines
11 KiB
Go
Raw Normal View History

// Copyright 2019 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 sdk
import (
"android/soong/android"
"log"
"os"
"testing"
"github.com/google/blueprint/proptools"
)
// Needed in an _test.go file in this package to ensure tests run correctly, particularly in IDE.
func TestMain(m *testing.M) {
if android.BuildOs != android.Linux {
// b/145598135 - Generating host snapshots for anything other than linux is not supported.
log.Printf("Skipping as sdk snapshot generation is only supported on %s not %s", android.Linux, android.BuildOs)
os.Exit(0)
}
runTestWithBuildDir(m)
}
func TestDepNotInRequiredSdks(t *testing.T) {
testSdkError(t, `module "myjavalib".*depends on "otherlib".*that isn't part of the required SDKs:.*`, `
sdk {
name: "mysdk",
java_header_libs: ["sdkmember"],
}
sdk_snapshot {
name: "mysdk@1",
java_header_libs: ["sdkmember_mysdk_1"],
}
java_import {
name: "sdkmember",
prefer: false,
host_supported: true,
}
java_import {
name: "sdkmember_mysdk_1",
sdk_member_name: "sdkmember",
host_supported: true,
}
java_library {
name: "myjavalib",
srcs: ["Test.java"],
libs: [
"sdkmember",
"otherlib",
],
system_modules: "none",
sdk_version: "none",
compile_dex: true,
host_supported: true,
apex_available: ["myapex"],
}
// this lib is no in mysdk
java_library {
name: "otherlib",
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
compile_dex: true,
host_supported: true,
}
apex {
name: "myapex",
java_libs: ["myjavalib"],
uses_sdks: ["mysdk@1"],
key: "myapex.key",
certificate: ":myapex.cert",
}
`)
}
// Ensure that prebuilt modules have the same effective visibility as the source
// modules.
func TestSnapshotVisibility(t *testing.T) {
packageBp := `
package {
default_visibility: ["//other/foo"],
}
sdk {
name: "mysdk",
visibility: [
"//other/foo",
// This short form will be replaced with //package:__subpackages__ in the
// generated sdk_snapshot.
":__subpackages__",
],
prebuilt_visibility: [
"//prebuilts/mysdk",
],
java_header_libs: [
"myjavalib",
"mypublicjavalib",
"mydefaultedjavalib",
"myprivatejavalib",
],
}
java_library {
name: "myjavalib",
// Uses package default visibility
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
}
java_defaults {
name: "java-defaults",
visibility: ["//other/bar"],
}
java_library {
name: "mypublicjavalib",
defaults: ["java-defaults"],
visibility: ["//visibility:public"],
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
}
java_defaults {
name: "myjavadefaults",
visibility: ["//other/bar"],
}
java_library {
name: "mydefaultedjavalib",
defaults: ["myjavadefaults"],
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
}
java_library {
name: "myprivatejavalib",
srcs: ["Test.java"],
visibility: ["//visibility:private"],
system_modules: "none",
sdk_version: "none",
}
`
result := testSdkWithFs(t, ``,
map[string][]byte{
"package/Test.java": nil,
"package/Android.bp": []byte(packageBp),
})
result.CheckSnapshot("mysdk", "package",
checkAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
java_import {
name: "mysdk_myjavalib@current",
sdk_member_name: "myjavalib",
visibility: [
"//other/foo",
"//package",
"//prebuilts/mysdk",
],
jars: ["java/myjavalib.jar"],
}
java_import {
name: "myjavalib",
prefer: false,
visibility: [
"//other/foo",
"//package",
"//prebuilts/mysdk",
],
jars: ["java/myjavalib.jar"],
}
java_import {
name: "mysdk_mypublicjavalib@current",
sdk_member_name: "mypublicjavalib",
visibility: ["//visibility:public"],
jars: ["java/mypublicjavalib.jar"],
}
java_import {
name: "mypublicjavalib",
prefer: false,
visibility: ["//visibility:public"],
jars: ["java/mypublicjavalib.jar"],
}
java_import {
name: "mysdk_mydefaultedjavalib@current",
sdk_member_name: "mydefaultedjavalib",
visibility: [
"//other/bar",
"//package",
"//prebuilts/mysdk",
],
jars: ["java/mydefaultedjavalib.jar"],
}
java_import {
name: "mydefaultedjavalib",
prefer: false,
visibility: [
"//other/bar",
"//package",
"//prebuilts/mysdk",
],
jars: ["java/mydefaultedjavalib.jar"],
}
java_import {
name: "mysdk_myprivatejavalib@current",
sdk_member_name: "myprivatejavalib",
visibility: [
"//package",
"//prebuilts/mysdk",
],
jars: ["java/myprivatejavalib.jar"],
}
java_import {
name: "myprivatejavalib",
prefer: false,
visibility: [
"//package",
"//prebuilts/mysdk",
],
jars: ["java/myprivatejavalib.jar"],
}
sdk_snapshot {
name: "mysdk@current",
visibility: [
"//other/foo",
"//package:__subpackages__",
],
java_header_libs: [
"mysdk_myjavalib@current",
"mysdk_mypublicjavalib@current",
"mysdk_mydefaultedjavalib@current",
"mysdk_myprivatejavalib@current",
],
}
`))
}
func TestPrebuiltVisibilityProperty_IsValidated(t *testing.T) {
testSdkError(t, `prebuilt_visibility: cannot mix "//visibility:private" with any other visibility rules`, `
sdk {
name: "mysdk",
prebuilt_visibility: [
"//foo",
"//visibility:private",
],
}
`)
}
func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) {
testSdkError(t, `prebuilt_visibility: "//visibility:private" does not widen the visibility`, `
sdk {
name: "mysdk",
prebuilt_visibility: [
"//visibility:private",
],
java_header_libs: [
"myjavalib",
],
}
java_library {
name: "myjavalib",
// Uses package default visibility
srcs: ["Test.java"],
system_modules: "none",
sdk_version: "none",
}
`)
}
func TestSDkInstall(t *testing.T) {
sdk := `
sdk {
name: "mysdk",
}
`
result := testSdkWithFs(t, ``,
map[string][]byte{
"Android.bp": []byte(sdk),
})
result.CheckSnapshot("mysdk", "",
checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
)
}
type EmbeddedPropertiesStruct struct {
S_Embedded_Common string `android:"arch_variant"`
S_Embedded_Different string `android:"arch_variant"`
}
type testPropertiesStruct struct {
name string
private string
Public_Kept string `sdk:"keep"`
S_Common string
S_Different string `android:"arch_variant"`
A_Common []string
A_Different []string `android:"arch_variant"`
F_Common *bool
F_Different *bool `android:"arch_variant"`
EmbeddedPropertiesStruct
}
func (p *testPropertiesStruct) optimizableProperties() interface{} {
return p
}
func (p *testPropertiesStruct) String() string {
return p.name
}
var _ propertiesContainer = (*testPropertiesStruct)(nil)
func TestCommonValueOptimization(t *testing.T) {
common := &testPropertiesStruct{name: "common"}
structs := []propertiesContainer{
&testPropertiesStruct{
name: "struct-0",
private: "common",
Public_Kept: "common",
S_Common: "common",
S_Different: "upper",
A_Common: []string{"first", "second"},
A_Different: []string{"alpha", "beta"},
F_Common: proptools.BoolPtr(false),
F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_upper",
},
},
&testPropertiesStruct{
name: "struct-1",
private: "common",
Public_Kept: "common",
S_Common: "common",
S_Different: "lower",
A_Common: []string{"first", "second"},
A_Different: []string{"alpha", "delta"},
F_Common: proptools.BoolPtr(false),
F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "embedded_lower",
},
},
}
extractor := newCommonValueExtractor(common)
h := TestHelper{t}
err := extractor.extractCommonProperties(common, structs)
h.AssertDeepEquals("unexpected error", nil, err)
h.AssertDeepEquals("common properties not correct",
&testPropertiesStruct{
name: "common",
private: "",
Public_Kept: "",
S_Common: "common",
S_Different: "",
A_Common: []string{"first", "second"},
A_Different: []string(nil),
F_Common: proptools.BoolPtr(false),
F_Different: nil,
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "embedded_common",
S_Embedded_Different: "",
},
},
common)
h.AssertDeepEquals("updated properties[0] not correct",
&testPropertiesStruct{
name: "struct-0",
private: "common",
Public_Kept: "common",
S_Common: "",
S_Different: "upper",
A_Common: nil,
A_Different: []string{"alpha", "beta"},
F_Common: nil,
F_Different: proptools.BoolPtr(false),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_upper",
},
},
structs[0])
h.AssertDeepEquals("updated properties[1] not correct",
&testPropertiesStruct{
name: "struct-1",
private: "common",
Public_Kept: "common",
S_Common: "",
S_Different: "lower",
A_Common: nil,
A_Different: []string{"alpha", "delta"},
F_Common: nil,
F_Different: proptools.BoolPtr(true),
EmbeddedPropertiesStruct: EmbeddedPropertiesStruct{
S_Embedded_Common: "",
S_Embedded_Different: "embedded_lower",
},
},
structs[1])
}
func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) {
common := &testPropertiesStruct{name: "common"}
structs := []propertiesContainer{
&testPropertiesStruct{
name: "struct-0",
S_Common: "should-be-but-is-not-common0",
},
&testPropertiesStruct{
name: "struct-1",
S_Common: "should-be-but-is-not-common1",
},
}
extractor := newCommonValueExtractor(common)
h := TestHelper{t}
err := extractor.extractCommonProperties(common, structs)
h.AssertErrorMessageEquals("unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties:
"struct-0" has value "should-be-but-is-not-common0"
"struct-1" has value "should-be-but-is-not-common1"`, err)
}