Merge "Add SystemPartitionParseTest to postsubmit" into rvc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8ced9207cc
@@ -118,6 +118,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"include-filter": "com.android.server.pm.UserSystemPackageInstallerTest"
|
"include-filter": "com.android.server.pm.UserSystemPackageInstallerTest"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include-filter": "com.android.server.pm.parsing.SystemPartitionParseTest"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import android.content.pm.ConfigurationInfo
|
|||||||
import android.content.pm.FeatureInfo
|
import android.content.pm.FeatureInfo
|
||||||
import android.content.pm.InstrumentationInfo
|
import android.content.pm.InstrumentationInfo
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.content.pm.PackageParser
|
import android.content.pm.PackageParser
|
||||||
import android.content.pm.PackageUserState
|
import android.content.pm.PackageUserState
|
||||||
import android.content.pm.PermissionInfo
|
import android.content.pm.PermissionInfo
|
||||||
@@ -38,7 +37,6 @@ import com.android.server.pm.parsing.pkg.AndroidPackage
|
|||||||
import com.android.server.pm.pkg.PackageStateUnserialized
|
import com.android.server.pm.pkg.PackageStateUnserialized
|
||||||
import com.android.server.testutils.mockThrowOnUnmocked
|
import com.android.server.testutils.mockThrowOnUnmocked
|
||||||
import com.android.server.testutils.whenever
|
import com.android.server.testutils.whenever
|
||||||
import org.junit.After
|
|
||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
import org.mockito.Mockito
|
import org.mockito.Mockito
|
||||||
import org.mockito.Mockito.anyInt
|
import org.mockito.Mockito.anyInt
|
||||||
@@ -49,7 +47,7 @@ open class AndroidPackageParsingTestBase {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val VERIFY_ALL_APKS = true
|
private const val VERIFY_ALL_APKS = false
|
||||||
|
|
||||||
/** For auditing memory usage differences */
|
/** For auditing memory usage differences */
|
||||||
private const val DUMP_HPROF_TO_EXTERNAL = false
|
private const val DUMP_HPROF_TO_EXTERNAL = false
|
||||||
@@ -93,21 +91,25 @@ open class AndroidPackageParsingTestBase {
|
|||||||
|
|
||||||
lateinit var newPackages: List<AndroidPackage>
|
lateinit var newPackages: List<AndroidPackage>
|
||||||
|
|
||||||
private val thrownInSetUp = mutableListOf<Throwable>()
|
|
||||||
|
|
||||||
@Suppress("ConstantConditionIf")
|
@Suppress("ConstantConditionIf")
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
fun setUpPackages() {
|
fun setUpPackages() {
|
||||||
this.oldPackages = apks.mapNotNull {
|
this.oldPackages = apks.mapNotNull {
|
||||||
tryOrNull {
|
try {
|
||||||
packageParser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
|
packageParser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
// Parsing issues will be caught by SystemPartitionParseTest
|
||||||
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.newPackages = apks.mapNotNull {
|
this.newPackages = apks.mapNotNull {
|
||||||
tryOrNull {
|
try {
|
||||||
packageParser2.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
|
packageParser2.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
// Parsing issues will be caught by SystemPartitionParseTest
|
||||||
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,41 +146,6 @@ open class AndroidPackageParsingTestBase {
|
|||||||
this.pkg = aPkg
|
this.pkg = aPkg
|
||||||
whenever(pkgState) { PackageStateUnserialized() }
|
whenever(pkgState) { PackageStateUnserialized() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T> tryOrNull(block: () -> T) = try {
|
|
||||||
block()
|
|
||||||
} catch (e: PackageParser.PackageParserException) {
|
|
||||||
if (e.error != PackageManager.INSTALL_PARSE_FAILED_SKIPPED) {
|
|
||||||
thrownInSetUp.add(e)
|
|
||||||
}
|
|
||||||
null
|
|
||||||
} catch (t: Throwable) {
|
|
||||||
thrownInSetUp.add(t)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
fun verifySetUpPackages() {
|
|
||||||
if (thrownInSetUp.isEmpty()) return
|
|
||||||
val exception = AssertionError("setUpPackages failed with ${thrownInSetUp.size} errors:\n" +
|
|
||||||
thrownInSetUp.joinToString(separator = "\n") { it.message.orEmpty() })
|
|
||||||
|
|
||||||
/*
|
|
||||||
Testing infrastructure doesn't currently support errors thrown in @AfterClass,
|
|
||||||
so instead it's thrown here. But to avoid throwing a massive repeated stack for every
|
|
||||||
test method, only throw on the first method run in the class, clearing the list so that
|
|
||||||
subsequent methods can run without failing. Doing this in @After lets true method
|
|
||||||
failures propagate, as those should throw before this does.
|
|
||||||
|
|
||||||
This will cause the failure to be attached to a different method depending on run order,
|
|
||||||
which could make comparisons difficult. So if a failure points here, it's worth
|
|
||||||
checking failures for all methods in all subclasses.
|
|
||||||
|
|
||||||
TODO: When infrastructure supports @AfterClass errors, move this
|
|
||||||
*/
|
|
||||||
thrownInSetUp.clear()
|
|
||||||
throw exception
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following methods dump an exact set of fields from the object to compare, because
|
// The following methods dump an exact set of fields from the object to compare, because
|
||||||
@@ -285,7 +252,8 @@ open class AndroidPackageParsingTestBase {
|
|||||||
secondaryCpuAbi=${this.secondaryCpuAbi}
|
secondaryCpuAbi=${this.secondaryCpuAbi}
|
||||||
secondaryNativeLibraryDir=${this.secondaryNativeLibraryDir}
|
secondaryNativeLibraryDir=${this.secondaryNativeLibraryDir}
|
||||||
sourceDir=${this.sourceDir}
|
sourceDir=${this.sourceDir}
|
||||||
splitDependencies=${this.splitDependencies.sequence().map { it.first to it.second?.contentToString() }.joinToString()}
|
splitDependencies=${this.splitDependencies.sequence()
|
||||||
|
.map { it.first to it.second?.contentToString() }.joinToString()}
|
||||||
splitNames=${this.splitNames?.contentToString()}
|
splitNames=${this.splitNames?.contentToString()}
|
||||||
splitPublicSourceDirs=${this.splitPublicSourceDirs?.contentToString()}
|
splitPublicSourceDirs=${this.splitPublicSourceDirs?.contentToString()}
|
||||||
splitSourceDirs=${this.splitSourceDirs?.contentToString()}
|
splitSourceDirs=${this.splitSourceDirs?.contentToString()}
|
||||||
@@ -348,7 +316,9 @@ open class AndroidPackageParsingTestBase {
|
|||||||
initOrder=${this.initOrder}
|
initOrder=${this.initOrder}
|
||||||
isSyncable=${this.isSyncable}
|
isSyncable=${this.isSyncable}
|
||||||
multiprocess=${this.multiprocess}
|
multiprocess=${this.multiprocess}
|
||||||
pathPermissions=${this.pathPermissions?.joinToString { "readPermission=${it.readPermission}\nwritePermission=${it.writePermission}" }}
|
pathPermissions=${this.pathPermissions?.joinToString {
|
||||||
|
"readPermission=${it.readPermission}\nwritePermission=${it.writePermission}"
|
||||||
|
}}
|
||||||
readPermission=${this.readPermission}
|
readPermission=${this.readPermission}
|
||||||
uriPermissionPatterns=${this.uriPermissionPatterns?.contentToString()}
|
uriPermissionPatterns=${this.uriPermissionPatterns?.contentToString()}
|
||||||
writePermission=${this.writePermission}
|
writePermission=${this.writePermission}
|
||||||
@@ -370,7 +340,9 @@ open class AndroidPackageParsingTestBase {
|
|||||||
compileSdkVersionCodename=${this.compileSdkVersionCodename}
|
compileSdkVersionCodename=${this.compileSdkVersionCodename}
|
||||||
configPreferences=${this.configPreferences?.joinToString { it.dumpToString() }}
|
configPreferences=${this.configPreferences?.joinToString { it.dumpToString() }}
|
||||||
coreApp=${this.coreApp}
|
coreApp=${this.coreApp}
|
||||||
featureGroups=${this.featureGroups?.joinToString { it.features?.joinToString { featureInfo -> featureInfo.dumpToString() }.orEmpty() }}
|
featureGroups=${this.featureGroups?.joinToString {
|
||||||
|
it.features?.joinToString { featureInfo -> featureInfo.dumpToString() }.orEmpty()
|
||||||
|
}}
|
||||||
firstInstallTime=${this.firstInstallTime}
|
firstInstallTime=${this.firstInstallTime}
|
||||||
gids=${gids?.contentToString()}
|
gids=${gids?.contentToString()}
|
||||||
installLocation=${this.installLocation}
|
installLocation=${this.installLocation}
|
||||||
@@ -396,7 +368,8 @@ open class AndroidPackageParsingTestBase {
|
|||||||
sharedUserId=${this.sharedUserId}
|
sharedUserId=${this.sharedUserId}
|
||||||
sharedUserLabel=${this.sharedUserLabel}
|
sharedUserLabel=${this.sharedUserLabel}
|
||||||
signatures=${this.signatures?.joinToString { it.toCharsString() }}
|
signatures=${this.signatures?.joinToString { it.toCharsString() }}
|
||||||
signingInfo=${this.signingInfo?.signingCertificateHistory?.joinToString { it.toCharsString() }.orEmpty()}
|
signingInfo=${this.signingInfo?.signingCertificateHistory
|
||||||
|
?.joinToString { it.toCharsString() }.orEmpty()}
|
||||||
splitNames=${this.splitNames?.contentToString()}
|
splitNames=${this.splitNames?.contentToString()}
|
||||||
splitRevisionCodes=${this.splitRevisionCodes?.contentToString()}
|
splitRevisionCodes=${this.splitRevisionCodes?.contentToString()}
|
||||||
targetOverlayableName=${this.targetOverlayableName}
|
targetOverlayableName=${this.targetOverlayableName}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.pm.parsing
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.PackageParser
|
||||||
|
import android.platform.test.annotations.Postsubmit
|
||||||
|
import com.android.server.pm.PackageManagerService
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test parses all the system APKs on the device image to ensure that they succeed.
|
||||||
|
*
|
||||||
|
* Any invalid APKs should be removed from the device or marked as skipped through any mechanism
|
||||||
|
* for ignoring packages.
|
||||||
|
*
|
||||||
|
* This test must run on deferred postsubmit. Targeted presubmit will not catch errors fast enough,
|
||||||
|
* and the low failure rate does not warrant global presubmit.
|
||||||
|
*/
|
||||||
|
@Postsubmit
|
||||||
|
class SystemPartitionParseTest {
|
||||||
|
|
||||||
|
private val APKS = PackageManagerService.SYSTEM_PARTITIONS
|
||||||
|
.flatMap { listOfNotNull(it.appFolder, it.privAppFolder, it.overlayFolder) }
|
||||||
|
.flatMap {
|
||||||
|
it.walkTopDown()
|
||||||
|
.filter { it.name.endsWith(".apk") }
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
.distinct()
|
||||||
|
|
||||||
|
private val parser = PackageParser2.forParsingFileWithDefaults()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun verify() {
|
||||||
|
val exceptions = APKS
|
||||||
|
.map {
|
||||||
|
runCatching {
|
||||||
|
parser.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mapNotNull { it.exceptionOrNull() }
|
||||||
|
.filterNot { (it as? PackageParser.PackageParserException)?.error ==
|
||||||
|
PackageManager.INSTALL_PARSE_FAILED_SKIPPED }
|
||||||
|
|
||||||
|
if (exceptions.isEmpty()) return
|
||||||
|
|
||||||
|
throw AssertionError("verify failed with ${exceptions.size} errors:\n" +
|
||||||
|
exceptions.joinToString(separator = "\n") { it.message.orEmpty() })
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user