blob: 2e14864c50018da060295d9eb96e81bb92ab3078 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.build.gradle.internal
import com.android.builder.core.ToolsRevisionUtils
import com.google.common.truth.Truth.assertThat
import com.android.repository.Revision
import com.android.sdklib.BuildToolInfo
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import java.io.File
class SdkParsingUtilsTest {
private val BUILD_TOOL_28_0_2_XML = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:repository
xmlns:ns2="http://schemas.android.com/repository/android/common/01"
xmlns:ns3="http://schemas.android.com/repository/android/generic/01"
xmlns:ns4="http://schemas.android.com/sdk/android/repo/addon2/01"
xmlns:ns5="http://schemas.android.com/sdk/android/repo/repository2/01"
xmlns:ns6="http://schemas.android.com/sdk/android/repo/sys-img2/01">
<license id="android-sdk-license" type="text">Very valid license</license>
<localPackage path="build-tools;28.0.2" obsolete="false">
<type-details xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:genericDetailsType"/>
<revision><major>28</major><minor>0</minor><micro>2</micro></revision>
<display-name>Android SDK Build-Tools 28.0.2</display-name>
<uses-license ref="android-sdk-license"/>
</localPackage>
</ns2:repository>
""".trimIndent()
private val BUILD_TOOL_28_0_3_XML = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:repository
xmlns:ns2="http://schemas.android.com/repository/android/common/01"
xmlns:ns3="http://schemas.android.com/repository/android/generic/01"
xmlns:ns4="http://schemas.android.com/sdk/android/repo/addon2/01"
xmlns:ns5="http://schemas.android.com/sdk/android/repo/repository2/01"
xmlns:ns6="http://schemas.android.com/sdk/android/repo/sys-img2/01">
<license id="android-sdk-license" type="text">Very valid license</license>
<localPackage path="build-tools;28.0.3" obsolete="false">
<type-details xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns3:genericDetailsType"/>
<revision><major>28</major><minor>0</minor><micro>3</micro></revision>
<display-name>Android SDK Build-Tools 28.0.3</display-name>
<uses-license ref="android-sdk-license"/>
</localPackage>
</ns2:repository>
""".trimIndent()
private val ADDON_XML = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:repository
xmlns:ns2="http://schemas.android.com/repository/android/common/01"
xmlns:ns3="http://schemas.android.com/repository/android/generic/01"
xmlns:ns4="http://schemas.android.com/sdk/android/repo/addon2/01"
xmlns:ns5="http://schemas.android.com/sdk/android/repo/repository2/01"
xmlns:ns6="http://schemas.android.com/sdk/android/repo/sys-img2/01">
<license id="android-sdk-license" type="text">Very valid license</license>
<localPackage path="add-ons;addon-google_apis-google-24" obsolete="false">
<type-details xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns4:addonDetailsType">
<api-level>24</api-level>
<codename></codename>
<vendor><id>google</id><display>Google Inc.</display></vendor>
<tag><id>google_apis</id><display>Google APIs</display></tag>
<libraries>
<library localJarPath="maps.jar" name="com.google.android.maps">
<description>API for Google Maps</description>
</library>
<library localJarPath="usb.jar" name="com.android.future.usb.accessory">
<description>API for USB Accessories</description>
</library>
<library localJarPath="effects.jar" name="com.google.android.media.effects">
<description>Collection of video effects</description>
</library>
</libraries>
</type-details>
<revision><major>1</major></revision>
<display-name>Google APIs</display-name>
<uses-license ref="android-sdk-license"/>
</localPackage>
</ns2:repository>
""".trimIndent()
private val PLATFORM_28_XML = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:repository
xmlns:ns2="http://schemas.android.com/repository/android/common/01"
xmlns:ns3="http://schemas.android.com/repository/android/generic/01"
xmlns:ns4="http://schemas.android.com/sdk/android/repo/addon2/01"
xmlns:ns5="http://schemas.android.com/sdk/android/repo/repository2/01"
xmlns:ns6="http://schemas.android.com/sdk/android/repo/sys-img2/01">
<license id="android-sdk-license" type="text">Very valid license</license>
<localPackage path="platforms;android-28" obsolete="false">
<type-details xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns5:platformDetailsType">
<api-level>28</api-level>
<codename></codename>
<layoutlib api="15"/>
</type-details>
<revision><major>6</major></revision>
<display-name>Android SDK Platform 28</display-name>
<uses-license ref="android-sdk-license"/>
</localPackage>
</ns2:repository>
""".trimIndent()
private val PLATFORM_28_OPTIONAL_JSON = """
[
{
"name": "org.apache.http.legacy",
"jar": "org.apache.http.legacy.jar",
"manifest": false
},
{
"name": "android.test.mock",
"jar": "android.test.mock.jar",
"manifest": false
},
{
"name": "android.test.base",
"jar": "android.test.base.jar",
"manifest": false
},
{
"name": "android.test.runner",
"jar": "android.test.runner.jar",
"manifest": false
}
]
""".trimIndent()
@get:Rule
val testFolder = TemporaryFolder()
@Test
fun buildBuildTools_ok() {
val sdkDir = testFolder.newFolder("sdk")
val buildToolDir = testFolder.newFolder("sdk", "build-tools", "28.0.3")
val revision = Revision.parseRevision("28.0.3")
populateBuildToolDirectory(buildToolDir, revision)
val packageXml = buildToolDir.resolve("package.xml")
packageXml.createNewFile()
packageXml.writeText(BUILD_TOOL_28_0_3_XML, Charsets.UTF_8)
val buildTool = buildBuildTools(sdkDir, revision)
assertThat(buildTool).isNotNull()
assertThat(buildTool!!.revision).isEqualTo(revision)
}
@Test
fun buildBuildTools_wrongBuildTool() {
val sdkDir = testFolder.newFolder("sdk")
val buildToolDir = testFolder.newFolder("sdk", "build-tools", "28.0.3")
populateBuildToolDirectory(buildToolDir, Revision.parseRevision("28.0.2"))
val packageXml = buildToolDir.resolve("package.xml")
packageXml.createNewFile()
packageXml.writeText(BUILD_TOOL_28_0_2_XML, Charsets.UTF_8)
val buildTool = buildBuildTools(sdkDir, Revision.parseRevision("28.0.3"))
assertThat(buildTool).isNull()
}
@Test
fun buildBuildTools_corruptBuildTool() {
val sdkDir = testFolder.newFolder("sdk")
val buildToolDir = testFolder.newFolder("sdk", "build-tools", "28.0.3")
val revision = Revision.parseRevision("28.0.3")
populateBuildToolDirectory(
buildToolDir, revision, setOf(BuildToolInfo.PathId.CORE_LAMBDA_STUBS))
val packageXml = buildToolDir.resolve("package.xml")
packageXml.createNewFile()
packageXml.writeText(BUILD_TOOL_28_0_3_XML, Charsets.UTF_8)
val buildTool = buildBuildTools(sdkDir, revision)
assertThat(buildTool).isNull()
}
@Test
fun parsePackage_ok() {
val xml = testFolder.newFile("package.xml")
xml.writeText(BUILD_TOOL_28_0_3_XML, Charsets.UTF_8)
val localPackage = parsePackage(xml)
assertThat(localPackage).isNotNull()
assertThat(localPackage!!.version).isEqualTo(Revision.parseRevision("28.0.3"))
assertThat(localPackage!!.displayName).isEqualTo("Android SDK Build-Tools 28.0.3")
}
@Test
fun parseAdditionalLibraries_ok() {
val xml = testFolder.newFile("package.xml")
xml.writeText(ADDON_XML, Charsets.UTF_8)
val localPackage = parsePackage(xml)
assertThat(localPackage).isNotNull()
val expectedJars = listOf("maps.jar", "usb.jar", "effects.jar")
.map { testFolder.root.resolve("libs").resolve(it).toPath() }
val optionalLibraries = parseAdditionalLibraries(localPackage!!).map { it.jar }
assertThat(optionalLibraries).containsExactlyElementsIn(expectedJars)
}
@Test
fun parseAdditionalLibraries_nonAddon() {
val xml = testFolder.newFile("package.xml")
xml.writeText(PLATFORM_28_XML, Charsets.UTF_8)
val localPackage = parsePackage(xml)
assertThat(localPackage).isNotNull()
val optionalLibraries = parseAdditionalLibraries(localPackage!!)
assertThat(optionalLibraries).isEmpty()
}
@Test
fun parseOptionalLibraries_ok() {
val xml = testFolder.newFile("package.xml")
xml.writeText(PLATFORM_28_XML, Charsets.UTF_8)
val optionalDir = testFolder.newFolder("optional")
val optionalJson = optionalDir.resolve("optional.json")
optionalJson.createNewFile()
optionalJson.writeText(PLATFORM_28_OPTIONAL_JSON, Charsets.UTF_8)
val localPackage = parsePackage(xml)
assertThat(localPackage).isNotNull()
val expectedJars = listOf(
"org.apache.http.legacy.jar",
"android.test.mock.jar",
"android.test.base.jar",
"android.test.runner.jar").map { optionalDir.resolve(it).toPath() }
val optionalLibraries = parseOptionalLibraries(localPackage!!).map { it.jar }
assertThat(optionalLibraries).containsExactlyElementsIn(expectedJars)
}
@Test
fun parseOptionalLibraries_missingOptionalJson() {
val xml = testFolder.newFile("package.xml")
xml.writeText(PLATFORM_28_XML, Charsets.UTF_8)
val localPackage = parsePackage(xml)
assertThat(localPackage).isNotNull()
val optionalLibraries = parseOptionalLibraries(localPackage!!)
assertThat(optionalLibraries).isEmpty()
}
private fun populateBuildToolDirectory(buildToolDir: File, buildToolRevision: Revision, skipSet: Set<BuildToolInfo.PathId> = emptySet()) {
val buildToolInfo = BuildToolInfo.fromStandardDirectoryLayout(buildToolRevision, buildToolDir.toPath())
for (id in BuildToolInfo.PathId.values()) {
if (!id.isPresentIn(buildToolRevision) || skipSet.contains(id)) {
continue
}
val buildToolComponent = File(buildToolInfo.getPath(id))
buildToolComponent.parentFile.mkdirs()
buildToolComponent.createNewFile()
}
}
}