Merge "Add parsing class parcelling tests"
This commit is contained in:
@@ -55,6 +55,8 @@ import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.overlay.OverlayPaths;
|
||||
import android.content.pm.parsing.ParsingPackageUtils;
|
||||
import android.content.pm.split.SplitAssetLoader;
|
||||
import android.content.pm.parsing.result.ParseResult;
|
||||
import android.content.pm.parsing.result.ParseTypeImpl;
|
||||
import android.content.res.ApkAssets;
|
||||
@@ -7425,7 +7427,7 @@ public class PackageParser {
|
||||
mCompileSdkVersionCodename = dest.readString();
|
||||
mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot);
|
||||
|
||||
mKeySetMapping = readKeySetMapping(dest);
|
||||
mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest);
|
||||
|
||||
cpuAbiOverride = dest.readString();
|
||||
use32bitAbi = (dest.readInt() == 1);
|
||||
@@ -7551,73 +7553,13 @@ public class PackageParser {
|
||||
dest.writeInt(mCompileSdkVersion);
|
||||
dest.writeString(mCompileSdkVersionCodename);
|
||||
dest.writeArraySet(mUpgradeKeySets);
|
||||
writeKeySetMapping(dest, mKeySetMapping);
|
||||
ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping);
|
||||
dest.writeString(cpuAbiOverride);
|
||||
dest.writeInt(use32bitAbi ? 1 : 0);
|
||||
dest.writeByteArray(restrictUpdateHash);
|
||||
dest.writeInt(visibleToInstantApps ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the keyset mapping to the provided package. {@code null} mappings are permitted.
|
||||
*/
|
||||
private static void writeKeySetMapping(
|
||||
Parcel dest, ArrayMap<String, ArraySet<PublicKey>> keySetMapping) {
|
||||
if (keySetMapping == null) {
|
||||
dest.writeInt(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
final int N = keySetMapping.size();
|
||||
dest.writeInt(N);
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
dest.writeString(keySetMapping.keyAt(i));
|
||||
ArraySet<PublicKey> keys = keySetMapping.valueAt(i);
|
||||
if (keys == null) {
|
||||
dest.writeInt(-1);
|
||||
continue;
|
||||
}
|
||||
|
||||
final int M = keys.size();
|
||||
dest.writeInt(M);
|
||||
for (int j = 0; j < M; j++) {
|
||||
dest.writeSerializable(keys.valueAt(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a keyset mapping from the given parcel at the given data position. May return
|
||||
* {@code null} if the serialized mapping was {@code null}.
|
||||
*/
|
||||
private static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(Parcel in) {
|
||||
final int N = in.readInt();
|
||||
if (N == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>();
|
||||
for (int i = 0; i < N; ++i) {
|
||||
String key = in.readString();
|
||||
final int M = in.readInt();
|
||||
if (M == -1) {
|
||||
keySetMapping.put(key, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
ArraySet<PublicKey> keys = new ArraySet<>(M);
|
||||
for (int j = 0; j < M; ++j) {
|
||||
PublicKey pk = (PublicKey) in.readSerializable();
|
||||
keys.add(pk);
|
||||
}
|
||||
|
||||
keySetMapping.put(key, keys);
|
||||
}
|
||||
|
||||
return keySetMapping;
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Package>() {
|
||||
public Package createFromParcel(Parcel in) {
|
||||
return new Package(in);
|
||||
|
||||
@@ -535,7 +535,7 @@ public class PackageInfoWithoutStateUtils {
|
||||
ai.setMaxAspectRatio(maxAspectRatio != null ? maxAspectRatio : 0f);
|
||||
Float minAspectRatio = a.getMinAspectRatio();
|
||||
ai.setMinAspectRatio(minAspectRatio != null ? minAspectRatio : 0f);
|
||||
ai.supportsSizeChanges = a.getSupportsSizeChanges();
|
||||
ai.supportsSizeChanges = a.isSupportsSizeChanges();
|
||||
ai.requestedVrComponent = a.getRequestedVrComponent();
|
||||
ai.rotationAnimation = a.getRotationAnimation();
|
||||
ai.colorMode = a.getColorMode();
|
||||
|
||||
@@ -360,7 +360,7 @@ public interface ParsingPackage extends ParsingPackageRead {
|
||||
|
||||
ParsingPackage setCompileSdkVersion(int compileSdkVersion);
|
||||
|
||||
ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename);
|
||||
ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName);
|
||||
|
||||
ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible);
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
|
||||
setCompileSdkVersion(manifestArray.getInteger(
|
||||
R.styleable.AndroidManifest_compileSdkVersion, 0));
|
||||
setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
|
||||
setCompileSdkVersionCodeName(manifestArray.getNonConfigurationString(
|
||||
R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
|
||||
|
||||
setIsolatedSplitLoading(manifestArray.getBoolean(
|
||||
@@ -2686,8 +2686,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
|
||||
this.compileSdkVersionCodeName = compileSdkVersionCodename;
|
||||
public ParsingPackage setCompileSdkVersionCodeName(String compileSdkVersionCodeName) {
|
||||
this.compileSdkVersionCodeName = compileSdkVersionCodeName;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
|
||||
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.ComponentName;
|
||||
@@ -423,6 +424,7 @@ public class ParsedActivity extends ParsedMainComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
|
||||
@Override
|
||||
public ParsedActivity createFromParcel(Parcel source) {
|
||||
@@ -513,10 +515,6 @@ public class ParsedActivity extends ParsedMainComponent {
|
||||
return minAspectRatio;
|
||||
}
|
||||
|
||||
public boolean getSupportsSizeChanges() {
|
||||
return supportsSizeChanges;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getRequestedVrComponent() {
|
||||
return requestedVrComponent;
|
||||
|
||||
@@ -43,8 +43,8 @@ import java.util.Map;
|
||||
/** @hide */
|
||||
public abstract class ParsedComponent implements Parcelable {
|
||||
|
||||
private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate(
|
||||
ParsedIntentInfo.ListParceler.class);
|
||||
private static final ParsedIntentInfo.ListParceler sForIntentInfos =
|
||||
Parcelling.Cache.getOrCreate(ParsedIntentInfo.ListParceler.class);
|
||||
|
||||
@NonNull
|
||||
@DataClass.ParcelWith(ForInternedString.class)
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.content.pm.parsing.component;
|
||||
|
||||
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.os.Parcel;
|
||||
@@ -94,6 +95,7 @@ public class ParsedInstrumentation extends ParsedComponent {
|
||||
this.functionalTest = in.readByte() != 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<ParsedInstrumentation> CREATOR =
|
||||
new Parcelable.Creator<ParsedInstrumentation>() {
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.content.pm.parsing.component;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Parcel;
|
||||
@@ -58,6 +59,7 @@ public final class ParsedIntentInfo extends IntentFilter {
|
||||
item.writeIntentInfoToParcel(dest, parcelFlags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ParsedIntentInfo unparcel(Parcel source) {
|
||||
return new ParsedIntentInfo(source);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.content.pm.parsing.component;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.os.Parcel;
|
||||
@@ -167,6 +168,7 @@ public class ParsedPermission extends ParsedComponent {
|
||||
this.knownCerts = sForStringSet.unparcel(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<ParsedPermission> CREATOR =
|
||||
new Parcelable.Creator<ParsedPermission>() {
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,6 @@ package android.content.pm.parsing.component;
|
||||
import static java.util.Collections.emptySet;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@@ -169,6 +169,7 @@ public class ParsedProvider extends ParsedMainComponent {
|
||||
this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
|
||||
@Override
|
||||
public ParsedProvider createFromParcel(Parcel source) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.content.pm.parsing.component;
|
||||
|
||||
import static android.content.pm.parsing.ParsingPackageImpl.sForInternedString;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.os.Parcel;
|
||||
@@ -83,6 +84,7 @@ public class ParsedService extends ParsedMainComponent {
|
||||
this.permission = sForInternedString.unparcel(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
|
||||
@Override
|
||||
public ParsedService createFromParcel(Parcel source) {
|
||||
|
||||
@@ -55,6 +55,7 @@ import java.util.UUID;
|
||||
*/
|
||||
public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
|
||||
|
||||
@NonNull
|
||||
public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
|
||||
@NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
|
||||
return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
|
||||
@@ -70,6 +71,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
|
||||
* this case only cares about
|
||||
* volumeUuid, just fake it rather than having separate method paths.
|
||||
*/
|
||||
@NonNull
|
||||
public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
|
||||
return ((ParsedPackage) PackageImpl.forTesting(packageName)
|
||||
.setVolumeUuid(volumeUuid)
|
||||
@@ -77,11 +79,13 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
|
||||
.hideAsFinal();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@VisibleForTesting
|
||||
public static ParsingPackage forTesting(String packageName) {
|
||||
return forTesting(packageName, "");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@VisibleForTesting
|
||||
public static ParsingPackage forTesting(String packageName, String baseCodePath) {
|
||||
return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
|
||||
@@ -568,6 +572,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka
|
||||
assignDerivedFields();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
|
||||
@Override
|
||||
public PackageImpl createFromParcel(Parcel source) {
|
||||
|
||||
@@ -32,6 +32,7 @@ android_test {
|
||||
"androidx.test.runner",
|
||||
"junit",
|
||||
"kotlin-test",
|
||||
"kotlin-reflect",
|
||||
"services.core",
|
||||
"servicestests-utils",
|
||||
"truth-prebuilt",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"presubmit": [
|
||||
{
|
||||
"name": "PackageManagerServiceUnitTests"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.ConfigurationInfo
|
||||
import android.content.pm.FeatureGroupInfo
|
||||
import android.content.pm.FeatureInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.SigningDetails
|
||||
import android.content.pm.parsing.ParsingPackage
|
||||
import android.content.pm.parsing.component.ParsedActivity
|
||||
import android.content.pm.parsing.component.ParsedAttribution
|
||||
import android.content.pm.parsing.component.ParsedComponent
|
||||
import android.content.pm.parsing.component.ParsedInstrumentation
|
||||
import android.content.pm.parsing.component.ParsedIntentInfo
|
||||
import android.content.pm.parsing.component.ParsedPermission
|
||||
import android.content.pm.parsing.component.ParsedPermissionGroup
|
||||
import android.content.pm.parsing.component.ParsedProcess
|
||||
import android.content.pm.parsing.component.ParsedProvider
|
||||
import android.content.pm.parsing.component.ParsedService
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.util.ArraySet
|
||||
import android.util.SparseArray
|
||||
import android.util.SparseIntArray
|
||||
import com.android.internal.R
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage
|
||||
import com.android.server.pm.parsing.pkg.PackageImpl
|
||||
import com.android.server.testutils.mockThrowOnUnmocked
|
||||
import com.android.server.testutils.whenever
|
||||
import java.security.KeyPairGenerator
|
||||
import java.security.PublicKey
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, PackageImpl::class) {
|
||||
|
||||
override val defaultImpl = PackageImpl.forTesting("com.example.test")
|
||||
override val creator = PackageImpl.CREATOR
|
||||
|
||||
override val excludedMethods = listOf(
|
||||
// Internal methods
|
||||
"toAppInfoToString",
|
||||
"toAppInfoWithoutState",
|
||||
"toAppInfoWithoutStateWithoutFlags",
|
||||
"assignDerivedFields",
|
||||
"buildFakeForDeletion",
|
||||
"capPermissionPriorities",
|
||||
"forParsing",
|
||||
"forTesting",
|
||||
"getBaseAppDataCredentialProtectedDirForSystemUser",
|
||||
"getBaseAppDataDeviceProtectedDirForSystemUser",
|
||||
"getBoolean",
|
||||
"setBoolean",
|
||||
"hideAsFinal",
|
||||
"hideAsParsed",
|
||||
"markNotActivitiesAsNotExportedIfSingleUser",
|
||||
"sortActivities",
|
||||
"sortReceivers",
|
||||
"sortServices",
|
||||
"setAllComponentsDirectBootAware",
|
||||
// Tested through setting minor/major manually
|
||||
"setLongVersionCode",
|
||||
"getLongVersionCode",
|
||||
// Tested through constructor
|
||||
"getManifestPackageName",
|
||||
"setManifestPackageName",
|
||||
// Utility methods
|
||||
"getStorageUuid",
|
||||
// Removal not tested, irrelevant for parcelling concerns
|
||||
"removeUsesOptionalLibrary",
|
||||
"clearAdoptPermissions",
|
||||
"clearOriginalPackages",
|
||||
"clearProtectedBroadcasts",
|
||||
"removePermission",
|
||||
"removeUsesLibrary",
|
||||
"removeUsesOptionalNativeLibrary",
|
||||
// Tested manually
|
||||
"getMimeGroups",
|
||||
"getRequestedPermissions",
|
||||
// Tested through asSplit
|
||||
"asSplit",
|
||||
"getSplitNames",
|
||||
"getSplitCodePaths",
|
||||
"getSplitRevisionCodes",
|
||||
"getSplitFlags",
|
||||
"getSplitClassLoaderNames",
|
||||
"getSplitDependencies",
|
||||
"setSplitCodePaths",
|
||||
"setSplitClassLoaderName",
|
||||
"setSplitHasCode",
|
||||
)
|
||||
|
||||
override val baseParams = listOf(
|
||||
AndroidPackage::getAppComponentFactory,
|
||||
AndroidPackage::getAutoRevokePermissions,
|
||||
AndroidPackage::getBackupAgentName,
|
||||
AndroidPackage::getBanner,
|
||||
AndroidPackage::getBaseApkPath,
|
||||
AndroidPackage::getBaseRevisionCode,
|
||||
AndroidPackage::getCategory,
|
||||
AndroidPackage::getClassLoaderName,
|
||||
AndroidPackage::getClassName,
|
||||
AndroidPackage::getCompatibleWidthLimitDp,
|
||||
AndroidPackage::getCompileSdkVersion,
|
||||
AndroidPackage::getCompileSdkVersionCodeName,
|
||||
AndroidPackage::getDataExtractionRules,
|
||||
AndroidPackage::getDescriptionRes,
|
||||
AndroidPackage::getFullBackupContent,
|
||||
AndroidPackage::getGwpAsanMode,
|
||||
AndroidPackage::getIconRes,
|
||||
AndroidPackage::getInstallLocation,
|
||||
AndroidPackage::getLabelRes,
|
||||
AndroidPackage::getLargestWidthLimitDp,
|
||||
AndroidPackage::getLogo,
|
||||
AndroidPackage::getManageSpaceActivityName,
|
||||
AndroidPackage::getMemtagMode,
|
||||
AndroidPackage::getMinSdkVersion,
|
||||
AndroidPackage::getNativeHeapZeroInitialized,
|
||||
AndroidPackage::getNativeLibraryDir,
|
||||
AndroidPackage::getNativeLibraryRootDir,
|
||||
AndroidPackage::getNetworkSecurityConfigRes,
|
||||
AndroidPackage::getNonLocalizedLabel,
|
||||
AndroidPackage::getOverlayCategory,
|
||||
AndroidPackage::getOverlayPriority,
|
||||
AndroidPackage::getOverlayTarget,
|
||||
AndroidPackage::getOverlayTargetName,
|
||||
AndroidPackage::getPackageName,
|
||||
AndroidPackage::getPath,
|
||||
AndroidPackage::getPermission,
|
||||
AndroidPackage::getPrimaryCpuAbi,
|
||||
AndroidPackage::getProcessName,
|
||||
AndroidPackage::getRealPackage,
|
||||
AndroidPackage::getRequiredAccountType,
|
||||
AndroidPackage::getRequiresSmallestWidthDp,
|
||||
AndroidPackage::getResizeableActivity,
|
||||
AndroidPackage::getRestrictedAccountType,
|
||||
AndroidPackage::getRoundIconRes,
|
||||
AndroidPackage::getSeInfo,
|
||||
AndroidPackage::getSeInfoUser,
|
||||
AndroidPackage::getSecondaryCpuAbi,
|
||||
AndroidPackage::getSecondaryNativeLibraryDir,
|
||||
AndroidPackage::getSharedUserId,
|
||||
AndroidPackage::getSharedUserLabel,
|
||||
AndroidPackage::getStaticSharedLibName,
|
||||
AndroidPackage::getStaticSharedLibVersion,
|
||||
AndroidPackage::getTargetSandboxVersion,
|
||||
AndroidPackage::getTargetSdkVersion,
|
||||
AndroidPackage::getTaskAffinity,
|
||||
AndroidPackage::getTheme,
|
||||
AndroidPackage::getUiOptions,
|
||||
AndroidPackage::getUid,
|
||||
AndroidPackage::getVersionName,
|
||||
AndroidPackage::getZygotePreloadName,
|
||||
AndroidPackage::isAllowAudioPlaybackCapture,
|
||||
AndroidPackage::isAllowBackup,
|
||||
AndroidPackage::isAllowClearUserData,
|
||||
AndroidPackage::isAllowClearUserDataOnFailedRestore,
|
||||
AndroidPackage::isAllowNativeHeapPointerTagging,
|
||||
AndroidPackage::isAllowTaskReparenting,
|
||||
AndroidPackage::isBackupInForeground,
|
||||
AndroidPackage::isBaseHardwareAccelerated,
|
||||
AndroidPackage::isCantSaveState,
|
||||
AndroidPackage::isCoreApp,
|
||||
AndroidPackage::isCrossProfile,
|
||||
AndroidPackage::isDebuggable,
|
||||
AndroidPackage::isDefaultToDeviceProtectedStorage,
|
||||
AndroidPackage::isDirectBootAware,
|
||||
AndroidPackage::isEnabled,
|
||||
AndroidPackage::isExternalStorage,
|
||||
AndroidPackage::isExtractNativeLibs,
|
||||
AndroidPackage::isFactoryTest,
|
||||
AndroidPackage::isForceQueryable,
|
||||
AndroidPackage::isFullBackupOnly,
|
||||
AndroidPackage::isGame,
|
||||
AndroidPackage::isHasCode,
|
||||
AndroidPackage::isHasDomainUrls,
|
||||
AndroidPackage::isHasFragileUserData,
|
||||
AndroidPackage::isIsolatedSplitLoading,
|
||||
AndroidPackage::isKillAfterRestore,
|
||||
AndroidPackage::isLargeHeap,
|
||||
AndroidPackage::isMultiArch,
|
||||
AndroidPackage::isNativeLibraryRootRequiresIsa,
|
||||
AndroidPackage::isOdm,
|
||||
AndroidPackage::isOem,
|
||||
AndroidPackage::isOverlay,
|
||||
AndroidPackage::isOverlayIsStatic,
|
||||
AndroidPackage::isPartiallyDirectBootAware,
|
||||
AndroidPackage::isPersistent,
|
||||
AndroidPackage::isPrivileged,
|
||||
AndroidPackage::isProduct,
|
||||
AndroidPackage::isProfileableByShell,
|
||||
AndroidPackage::isRequestLegacyExternalStorage,
|
||||
AndroidPackage::isRequiredForAllUsers,
|
||||
AndroidPackage::isResizeableActivityViaSdkVersion,
|
||||
AndroidPackage::isRestoreAnyVersion,
|
||||
AndroidPackage::isSignedWithPlatformKey,
|
||||
AndroidPackage::isStaticSharedLibrary,
|
||||
AndroidPackage::isStub,
|
||||
AndroidPackage::isSupportsRtl,
|
||||
AndroidPackage::isSystem,
|
||||
AndroidPackage::isSystemExt,
|
||||
AndroidPackage::isTestOnly,
|
||||
AndroidPackage::isUse32BitAbi,
|
||||
AndroidPackage::isUseEmbeddedDex,
|
||||
AndroidPackage::isUsesCleartextTraffic,
|
||||
AndroidPackage::isUsesNonSdkApi,
|
||||
AndroidPackage::isVendor,
|
||||
AndroidPackage::isVisibleToInstantApps,
|
||||
AndroidPackage::isVmSafeMode,
|
||||
AndroidPackage::getMaxAspectRatio,
|
||||
AndroidPackage::getMinAspectRatio,
|
||||
AndroidPackage::hasPreserveLegacyExternalStorage,
|
||||
AndroidPackage::hasRequestForegroundServiceExemption,
|
||||
AndroidPackage::hasRequestRawExternalStorageAccess,
|
||||
)
|
||||
|
||||
override fun extraParams() = listOf(
|
||||
getter(AndroidPackage::getVolumeUuid, "57554103-df3e-4475-ae7a-8feba49353ac"),
|
||||
getter(AndroidPackage::isProfileable, true),
|
||||
getter(AndroidPackage::getVersionCode, 3),
|
||||
getter(AndroidPackage::getVersionCodeMajor, 9),
|
||||
getter(AndroidPackage::getUpgradeKeySets, setOf("testUpgradeKeySet")),
|
||||
getter(AndroidPackage::isAnyDensity, false, 0),
|
||||
getter(AndroidPackage::isResizeable, false, 0),
|
||||
getter(AndroidPackage::isSupportsSmallScreens, false, 0),
|
||||
getter(AndroidPackage::isSupportsNormalScreens, false, 0),
|
||||
getter(AndroidPackage::isSupportsLargeScreens, false, 0),
|
||||
getter(AndroidPackage::isSupportsExtraLargeScreens, false, 0),
|
||||
adder(AndroidPackage::getAdoptPermissions, "test.adopt.PERMISSION"),
|
||||
adder(AndroidPackage::getOriginalPackages, "com.test.original"),
|
||||
adder(AndroidPackage::getImplicitPermissions, "test.implicit.PERMISSION"),
|
||||
adder(AndroidPackage::getLibraryNames, "testLibraryName"),
|
||||
adder(AndroidPackage::getProtectedBroadcasts, "test.protected.BROADCAST"),
|
||||
adder(AndroidPackage::getQueriesPackages, "com.test.package.queries"),
|
||||
adder(AndroidPackage::getQueriesProviders, "com.test.package.queries.provider"),
|
||||
adder(AndroidPackage::getUsesLibraries, "testUsesLibrary"),
|
||||
adder(AndroidPackage::getUsesNativeLibraries, "testUsesNativeLibrary"),
|
||||
adder(AndroidPackage::getUsesOptionalLibraries, "testUsesOptionalLibrary"),
|
||||
adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"),
|
||||
adder(AndroidPackage::getUsesStaticLibraries, "testUsesStaticLibrary"),
|
||||
getSetByValue(
|
||||
AndroidPackage::getUsesStaticLibrariesVersions,
|
||||
PackageImpl::addUsesStaticLibraryVersion,
|
||||
(testCounter++).toLong(),
|
||||
transformGet = { it?.singleOrNull() }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::areAttributionsUserVisible,
|
||||
ParsingPackage::setAttributionsAreUserVisible,
|
||||
true
|
||||
),
|
||||
getSetByValue2(
|
||||
AndroidPackage::getOverlayables,
|
||||
PackageImpl::addOverlayable,
|
||||
"testOverlayableName" to "testActorName",
|
||||
transformGet = { "testOverlayableName" to it["testOverlayableName"] }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getMetaData,
|
||||
PackageImpl::setMetaData,
|
||||
"testBundleKey" to "testBundleValue",
|
||||
transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
|
||||
transformSet = { Bundle().apply { putString(it.first, it.second) } }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getAttributions,
|
||||
PackageImpl::addAttribution,
|
||||
Triple("testTag", 13, listOf("testInherit")),
|
||||
transformGet = { it.singleOrNull()?.let { Triple(it.tag, it.label, it.inheritFrom) } },
|
||||
transformSet = { it?.let { ParsedAttribution(it.first, it.second, it.third) } }
|
||||
),
|
||||
getSetByValue2(
|
||||
AndroidPackage::getKeySetMapping,
|
||||
PackageImpl::addKeySet,
|
||||
"testKeySetName" to testKey(),
|
||||
transformGet = { "testKeySetName" to it["testKeySetName"]?.singleOrNull() },
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getPermissionGroups,
|
||||
PackageImpl::addPermissionGroup,
|
||||
"test.permission.GROUP",
|
||||
transformGet = { it.singleOrNull()?.name },
|
||||
transformSet = { ParsedPermissionGroup().apply { setName(it) } }
|
||||
),
|
||||
getSetByValue2(
|
||||
AndroidPackage::getPreferredActivityFilters,
|
||||
PackageImpl::addPreferredActivityFilter,
|
||||
"TestClassName" to ParsedIntentInfo().apply {
|
||||
addDataScheme("http")
|
||||
addDataAuthority("test.pm.server.android.com", null)
|
||||
},
|
||||
transformGet = { it.singleOrNull()?.let { it.first to it.second } },
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
{ it.first },
|
||||
{ it.second.schemesIterator().asSequence().singleOrNull() },
|
||||
{ it.second.authoritiesIterator().asSequence().singleOrNull()?.host },
|
||||
)
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getQueriesIntents,
|
||||
PackageImpl::addQueriesIntent,
|
||||
Intent(Intent.ACTION_VIEW, Uri.parse("https://test.pm.server.android.com")),
|
||||
transformGet = { it.singleOrNull() },
|
||||
compare = { first, second -> first?.filterEquals(second) },
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getRestrictUpdateHash,
|
||||
PackageImpl::setRestrictUpdateHash,
|
||||
byteArrayOf(0, 1, 2, 3, 4),
|
||||
compare = ByteArray::contentEquals
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getSigningDetails,
|
||||
PackageImpl::setSigningDetails,
|
||||
testKey(),
|
||||
transformGet = { it.publicKeys?.takeIf { it.size > 0 }?.valueAt(0) },
|
||||
transformSet = {
|
||||
SigningDetails(
|
||||
null,
|
||||
SigningDetails.SignatureSchemeVersion.UNKNOWN,
|
||||
ArraySet<PublicKey>().apply { add(it) },
|
||||
null
|
||||
)
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getUsesStaticLibrariesCertDigests,
|
||||
PackageImpl::addUsesStaticLibraryCertDigests,
|
||||
arrayOf("testCertDigest"),
|
||||
transformGet = { it?.singleOrNull() },
|
||||
compare = Array<String?>?::contentEquals
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getActivities,
|
||||
PackageImpl::addActivity,
|
||||
"TestActivityName",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getReceivers,
|
||||
PackageImpl::addReceiver,
|
||||
"TestReceiverName",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { ParsedActivity().apply { name = it }.withMimeGroups() }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getServices,
|
||||
PackageImpl::addService,
|
||||
"TestServiceName",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { ParsedService().apply { name = it }.withMimeGroups() }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getProviders,
|
||||
PackageImpl::addProvider,
|
||||
"TestProviderName",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { ParsedProvider().apply { name = it }.withMimeGroups() }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getInstrumentations,
|
||||
PackageImpl::addInstrumentation,
|
||||
"TestInstrumentationName",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { ParsedInstrumentation().apply { name = it } }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getConfigPreferences,
|
||||
PackageImpl::addConfigPreference,
|
||||
testCounter++,
|
||||
transformGet = { it.singleOrNull()?.reqGlEsVersion ?: -1 },
|
||||
transformSet = { ConfigurationInfo().apply { reqGlEsVersion = it } }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getFeatureGroups,
|
||||
PackageImpl::addFeatureGroup,
|
||||
"test.feature.GROUP",
|
||||
transformGet = { it.singleOrNull()?.features?.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = {
|
||||
FeatureGroupInfo().apply {
|
||||
features = arrayOf(FeatureInfo().apply { name = it })
|
||||
}
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getPermissions,
|
||||
PackageImpl::addPermission,
|
||||
"test.PERMISSION",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { ParsedPermission().apply { name = it } }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getUsesPermissions,
|
||||
PackageImpl::addUsesPermission,
|
||||
"test.USES_PERMISSION",
|
||||
transformGet = {
|
||||
// Need to strip implicit permission, which calls addUsesPermission when added
|
||||
it.filterNot { it.name == "test.implicit.PERMISSION" }
|
||||
.singleOrNull()?.name.orEmpty()
|
||||
},
|
||||
transformSet = { ParsedUsesPermission(it, 0) }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getReqFeatures,
|
||||
PackageImpl::addReqFeature,
|
||||
"test.feature.INFO",
|
||||
transformGet = { it.singleOrNull()?.name.orEmpty() },
|
||||
transformSet = { FeatureInfo().apply { name = it } }
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getMinExtensionVersions,
|
||||
PackageImpl::setMinExtensionVersions,
|
||||
SparseIntArray().apply { put(testCounter++, testCounter++) },
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
{ it.size() },
|
||||
{ it.keyAt(0) },
|
||||
{ it.valueAt(0) },
|
||||
)
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getProcesses,
|
||||
PackageImpl::setProcesses,
|
||||
mapOf("testProcess" to ParsedProcess().apply { name = "testProcessName" }),
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
{ it["testProcess"]?.name },
|
||||
)
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
AndroidPackage::getProperties,
|
||||
PackageImpl::addProperty,
|
||||
PackageManager.Property(
|
||||
"testPropertyName",
|
||||
"testPropertyValue",
|
||||
"testPropertyClassName",
|
||||
"testPropertyPackageName"
|
||||
),
|
||||
transformGet = { it["testPropertyName"] },
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
PackageManager.Property::getName,
|
||||
PackageManager.Property::getClassName,
|
||||
PackageManager.Property::getPackageName,
|
||||
PackageManager.Property::getString,
|
||||
)
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
override fun initialObject() = PackageImpl.forParsing(
|
||||
"com.example.test",
|
||||
"/test/test/base.apk",
|
||||
"/test/test",
|
||||
mockThrowOnUnmocked {
|
||||
whenever(getInteger(R.styleable.AndroidManifest_revisionCode, 0)) { 4 }
|
||||
whenever(getBoolean(R.styleable.AndroidManifest_isolatedSplits, false)) { true }
|
||||
|
||||
// Return invalid values here so that the getter/setter is tested properly
|
||||
whenever(getInteger(R.styleable.AndroidManifest_versionCode, 0)) { -1 }
|
||||
whenever(getInteger(R.styleable.AndroidManifest_versionCodeMajor, 0)) { -1 }
|
||||
whenever(
|
||||
getNonConfigurationString(
|
||||
R.styleable.AndroidManifest_versionName,
|
||||
0
|
||||
)
|
||||
) { "" }
|
||||
whenever(getInteger(R.styleable.AndroidManifest_compileSdkVersion, 0)) { 31 }
|
||||
whenever(
|
||||
getNonConfigurationString(
|
||||
R.styleable.AndroidManifest_compileSdkVersionCodename,
|
||||
0
|
||||
)
|
||||
) { "" }
|
||||
},
|
||||
true
|
||||
)
|
||||
.asSplit(
|
||||
arrayOf("testSplitNameZero", "testSplitNameOne"),
|
||||
arrayOf("/test/testSplitZero.apk", "/test/testSplitOne.apk"),
|
||||
intArrayOf(10, 11),
|
||||
SparseArray<IntArray>().apply {
|
||||
put(0, intArrayOf(-1))
|
||||
put(1, intArrayOf(0))
|
||||
}
|
||||
)
|
||||
.setSplitHasCode(0, true)
|
||||
.setSplitHasCode(1, false)
|
||||
.setSplitClassLoaderName(0, "testSplitClassLoaderNameZero")
|
||||
.setSplitClassLoaderName(1, "testSplitClassLoaderNameOne")
|
||||
|
||||
override fun extraAssertions(before: Parcelable, after: Parcelable) {
|
||||
super.extraAssertions(before, after)
|
||||
after as PackageImpl
|
||||
expect.that(after.manifestPackageName).isEqualTo("com.example.test")
|
||||
expect.that(after.isCoreApp).isTrue()
|
||||
expect.that(after.isIsolatedSplitLoading).isEqualTo(true)
|
||||
expect.that(after.longVersionCode).isEqualTo(38654705667)
|
||||
expect.that(after.requestedPermissions)
|
||||
.containsExactlyElementsIn(after.usesPermissions.map { it.name })
|
||||
.inOrder()
|
||||
|
||||
expect.that(after.mimeGroups).containsExactly(
|
||||
"TestActivityName/mimeGroup",
|
||||
"TestReceiverName/mimeGroup",
|
||||
"TestServiceName/mimeGroup",
|
||||
"TestProviderName/mimeGroup"
|
||||
)
|
||||
|
||||
expect.that(after.splitNames).asList()
|
||||
.containsExactly("testSplitNameZero", "testSplitNameOne")
|
||||
.inOrder()
|
||||
expect.that(after.splitCodePaths).asList()
|
||||
.containsExactly("/test/testSplitZero.apk", "/test/testSplitOne.apk")
|
||||
.inOrder()
|
||||
expect.that(after.splitRevisionCodes).asList()
|
||||
.containsExactly(10, 11)
|
||||
.inOrder()
|
||||
expect.that(after.splitFlags).asList()
|
||||
.containsExactly(ApplicationInfo.FLAG_HAS_CODE, 0)
|
||||
.inOrder()
|
||||
expect.that(after.splitClassLoaderNames).asList()
|
||||
.containsExactly("testSplitClassLoaderNameZero", "testSplitClassLoaderNameOne")
|
||||
.inOrder()
|
||||
|
||||
expect.that(after.splitDependencies).isNotNull()
|
||||
after.splitDependencies?.let {
|
||||
expect.that(it.size()).isEqualTo(2)
|
||||
expect.that(it.get(0)).asList().containsExactly(-1)
|
||||
expect.that(it.get(1)).asList().containsExactly(0)
|
||||
}
|
||||
}
|
||||
|
||||
private fun testKey() = KeyPairGenerator.getInstance("RSA")
|
||||
.generateKeyPair()
|
||||
.public
|
||||
|
||||
private fun <T : ParsedComponent> T.withMimeGroups() = apply {
|
||||
val componentName = name
|
||||
addIntent(ParsedIntentInfo().apply {
|
||||
addMimeGroup("$componentName/mimeGroup")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.android.server.pm.test.util.IgnoreableExpect
|
||||
import com.google.common.truth.Expect
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestRule
|
||||
import java.util.Objects
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction
|
||||
import kotlin.reflect.KFunction1
|
||||
import kotlin.reflect.KFunction2
|
||||
import kotlin.reflect.KFunction3
|
||||
import kotlin.reflect.KVisibility
|
||||
import kotlin.reflect.full.allSuperclasses
|
||||
import kotlin.reflect.full.createInstance
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
import kotlin.reflect.full.memberFunctions
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.full.staticProperties
|
||||
import kotlin.reflect.jvm.jvmErasure
|
||||
|
||||
|
||||
@ExperimentalContracts
|
||||
abstract class ParcelableComponentTest(
|
||||
private val getterType: KClass<*>,
|
||||
private val setterType: KClass<out Parcelable>
|
||||
) {
|
||||
|
||||
companion object {
|
||||
private val DEFAULT_EXCLUDED = listOf(
|
||||
// Java
|
||||
"toString",
|
||||
"equals",
|
||||
"hashCode",
|
||||
// Parcelable
|
||||
"getStability",
|
||||
"describeContents",
|
||||
"writeToParcel",
|
||||
// @DataClass
|
||||
"__metadata"
|
||||
)
|
||||
}
|
||||
|
||||
internal val ignoreableExpect = IgnoreableExpect()
|
||||
|
||||
// Hides internal type
|
||||
@get:Rule
|
||||
val ignoreableAsTestRule: TestRule = ignoreableExpect
|
||||
|
||||
val expect: Expect
|
||||
get() = ignoreableExpect.expect
|
||||
|
||||
protected var testCounter = 1
|
||||
|
||||
protected abstract val defaultImpl: Any
|
||||
protected abstract val creator: Parcelable.Creator<out Parcelable>
|
||||
|
||||
protected open val excludedMethods: Collection<String> = emptyList()
|
||||
|
||||
protected abstract val baseParams: Collection<KFunction1<*, Any?>>
|
||||
|
||||
private val getters = getterType.memberFunctions
|
||||
.filterNot { DEFAULT_EXCLUDED.contains(it.name) }
|
||||
|
||||
private val setters = setterType.memberFunctions
|
||||
.filterNot { DEFAULT_EXCLUDED.contains(it.name) }
|
||||
|
||||
constructor(kClass: KClass<out Parcelable>) : this(kClass, kClass)
|
||||
|
||||
@Before
|
||||
fun checkNoPublicFields() {
|
||||
// Fields are not currently testable, and the idea is to enforce interface access for
|
||||
// immutability purposes, so disallow any public fields from existing.
|
||||
expect.that(getterType.memberProperties.filter { it.visibility == KVisibility.PUBLIC }
|
||||
.filterNot { DEFAULT_EXCLUDED.contains(it.name) })
|
||||
.isEmpty()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <ObjectType, ReturnType> buildParams(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
): Param? {
|
||||
return buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(
|
||||
getFunction,
|
||||
autoValue(getFunction) as ReturnType ?: return null
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> buildParams(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
value: SetType,
|
||||
): Param? {
|
||||
return getSetByValue<ObjectType, ReturnType, SetType, Any?>(
|
||||
getFunction,
|
||||
findSetFunction(getFunction) ?: return null,
|
||||
value
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <ObjectType, ReturnType> findSetFunction(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>
|
||||
): KFunction2<ObjectType, ReturnType, Any?>? {
|
||||
val getFunctionName = getFunction.name
|
||||
val prefix = when {
|
||||
getFunctionName.startsWith("get") -> "get"
|
||||
getFunctionName.startsWith("is") -> "is"
|
||||
getFunctionName.startsWith("has") -> "has"
|
||||
else -> throw IllegalArgumentException("Unsupported method name $getFunctionName")
|
||||
}
|
||||
val setFunctionName = "set" + getFunctionName.removePrefix(prefix)
|
||||
val setFunction = setters.filter { it.name == setFunctionName }
|
||||
.minByOrNull { it.parameters.size }
|
||||
|
||||
if (setFunction == null) {
|
||||
expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
|
||||
.fail()
|
||||
return null
|
||||
}
|
||||
|
||||
return setFunction as KFunction2<ObjectType, ReturnType, Any?>
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <ObjectType, ReturnType, SetType> findAddFunction(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>
|
||||
): KFunction2<ObjectType, SetType, Any?>? {
|
||||
val getFunctionName = getFunction.name
|
||||
if (!getFunctionName.startsWith("get")) {
|
||||
throw IllegalArgumentException("Unsupported method name $getFunctionName")
|
||||
}
|
||||
|
||||
val setFunctionName = "add" + getFunctionName.removePrefix("get").run {
|
||||
// Remove plurality
|
||||
when {
|
||||
endsWith("ies") -> "${removeSuffix("ies")}y"
|
||||
endsWith("s") -> removeSuffix("s")
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
||||
val setFunction = setters.filter { it.name == setFunctionName }
|
||||
.minByOrNull { it.parameters.size }
|
||||
|
||||
if (setFunction == null) {
|
||||
expect.withMessage("$getFunctionName does not have corresponding $setFunctionName")
|
||||
.fail()
|
||||
return null
|
||||
}
|
||||
|
||||
return setFunction as KFunction2<ObjectType, SetType, Any?>
|
||||
}
|
||||
|
||||
protected fun <ObjectType, ReturnType> getter(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
valueToSet: ReturnType
|
||||
) = buildParams<ObjectType, ReturnType, ReturnType, ReturnType>(getFunction, valueToSet)
|
||||
|
||||
protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getter(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
expectedValue: CompareType,
|
||||
valueToSet: SetType
|
||||
): Param? {
|
||||
return getSetByValue(
|
||||
getFunction,
|
||||
findSetFunction(getFunction) ?: return null,
|
||||
value = expectedValue,
|
||||
transformSet = { valueToSet }
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
protected fun <ObjectType, ReturnType> adder(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
value: ReturnType,
|
||||
): Param? {
|
||||
return getSetByValue(
|
||||
getFunction,
|
||||
findAddFunction<ObjectType, Any?, ReturnType>(getFunction) ?: return null,
|
||||
value,
|
||||
transformGet = {
|
||||
// Primitive arrays don't implement Iterable, so cast manually
|
||||
when (it) {
|
||||
is BooleanArray -> it.singleOrNull()
|
||||
is IntArray -> it.singleOrNull()
|
||||
is LongArray -> it.singleOrNull()
|
||||
is Iterable<*> -> it.singleOrNull()
|
||||
else -> null
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to provide custom getter and setter logic for values which are not simple primitives
|
||||
* or cannot be directly compared using [Objects.equals].
|
||||
*
|
||||
* @param getFunction the getter function which will be called and marked as tested
|
||||
* @param setFunction the setter function which will be called and marked as tested
|
||||
* @param value the value for comparison through the parcel-unparcel cycle, which can be
|
||||
* anything, like the [String] ID of an inner object
|
||||
* @param transformGet the function to transform the result of [getFunction] into [value]
|
||||
* @param transformSet the function to transform [value] into an input for [setFunction]
|
||||
* @param compare the function that compares the pre/post-parcel [value] objects
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
protected fun <ObjectType, ReturnType, SetType : Any?, CompareType : Any?> getSetByValue(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
setFunction: KFunction2<ObjectType, SetType, Any?>,
|
||||
value: CompareType,
|
||||
transformGet: (ReturnType) -> CompareType = { it as CompareType },
|
||||
transformSet: (CompareType) -> SetType = { it as SetType },
|
||||
compare: (CompareType, CompareType) -> Boolean? = Objects::equals
|
||||
) = Param(
|
||||
getFunction.name,
|
||||
{ transformGet(getFunction.call(it as ObjectType)) },
|
||||
setFunction.name,
|
||||
{ setFunction.call(it.first() as ObjectType, transformSet(it[1] as CompareType)) },
|
||||
{ value },
|
||||
{ first, second -> compare(first as CompareType, second as CompareType) == true }
|
||||
)
|
||||
|
||||
/**
|
||||
* Variant of [getSetByValue] that allows specifying a [setFunction] with 2 inputs.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
protected fun <ObjectType, ReturnType, SetType1 : Any?, SetType2 : Any?, CompareType : Any?>
|
||||
getSetByValue2(
|
||||
getFunction: KFunction1<ObjectType, ReturnType>,
|
||||
setFunction: KFunction3<ObjectType, SetType1, SetType2, Any>,
|
||||
value: CompareType,
|
||||
transformGet: (ReturnType) -> CompareType = { it as CompareType },
|
||||
transformSet: (CompareType) -> Pair<SetType1, SetType2> =
|
||||
{ it as Pair<SetType1, SetType2> },
|
||||
compare: (CompareType, CompareType) -> Boolean = Objects::equals
|
||||
) = Param(
|
||||
getFunction.name,
|
||||
{ transformGet(getFunction.call(it as ObjectType)) },
|
||||
setFunction.name,
|
||||
{
|
||||
val pair = transformSet(it[1] as CompareType)
|
||||
setFunction.call(it.first() as ObjectType, pair.first, pair.second)
|
||||
},
|
||||
{ value },
|
||||
{ first, second -> compare(first as CompareType, second as CompareType) }
|
||||
)
|
||||
|
||||
protected fun autoValue(getFunction: KFunction<*>) = when (getFunction.returnType.jvmErasure) {
|
||||
Boolean::class -> (getFunction.call(defaultImpl) as Boolean?)?.not() ?: true
|
||||
CharSequence::class,
|
||||
String::class -> getFunction.name + "TEST"
|
||||
Int::class -> testCounter++
|
||||
Long::class -> (testCounter++).toLong()
|
||||
Float::class -> (testCounter++).toFloat()
|
||||
else -> {
|
||||
expect.withMessage("${getFunction.name} needs to provide value").fail()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies two instances are equivalent via a series of properties. For use when a public API
|
||||
* class has not implemented equals.
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
protected fun <T : Any> equalBy(
|
||||
first: T?,
|
||||
second: T?,
|
||||
vararg properties: (T) -> Any?
|
||||
) = properties.all { property ->
|
||||
first?.let { property(it) } == second?.let { property(it) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun valueComparison() {
|
||||
val params = baseParams.mapNotNull(::buildParams) + extraParams().filterNotNull()
|
||||
val before = initialObject()
|
||||
|
||||
params.forEach { it.setFunction(arrayOf(before, it.value())) }
|
||||
|
||||
val parcel = Parcel.obtain()
|
||||
writeToParcel(parcel, before)
|
||||
|
||||
val dataSize = parcel.dataSize()
|
||||
|
||||
parcel.setDataPosition(0)
|
||||
|
||||
val after = creator.createFromParcel(parcel)
|
||||
|
||||
expect.withMessage("Mismatched write and read data sizes")
|
||||
.that(parcel.dataPosition())
|
||||
.isEqualTo(dataSize)
|
||||
|
||||
parcel.recycle()
|
||||
|
||||
runAssertions(params, before, after)
|
||||
}
|
||||
|
||||
@Test
|
||||
open fun parcellingSize() {
|
||||
val parcelOne = Parcel.obtain()
|
||||
writeToParcel(parcelOne, initialObject())
|
||||
|
||||
val parcelTwo = Parcel.obtain()
|
||||
initialObject().writeToParcel(parcelTwo, 0)
|
||||
|
||||
val superDataSizes = setterType.allSuperclasses
|
||||
.filter { it.isSubclassOf(Parcelable::class) }
|
||||
.mapNotNull { it.memberFunctions.find { it.name == "writeToParcel" } }
|
||||
.filter { it.isFinal }
|
||||
.map {
|
||||
val parcel = Parcel.obtain()
|
||||
initialObject().writeToParcel(parcel, 0)
|
||||
parcel.dataSize().also { parcel.recycle() }
|
||||
}
|
||||
|
||||
if ((superDataSizes + parcelOne.dataSize() + parcelTwo.dataSize()).distinct().size != 1) {
|
||||
listOf(getterType, setterType).distinct().forEach {
|
||||
val creatorProperties = it.staticProperties.filter { it.name == "CREATOR" }
|
||||
if (creatorProperties.size > 1) {
|
||||
expect.withMessage(
|
||||
"Multiple matching CREATOR fields found for" +
|
||||
it.qualifiedName
|
||||
)
|
||||
.that(creatorProperties)
|
||||
.hasSize(1)
|
||||
} else {
|
||||
val creator = creatorProperties.single().get()
|
||||
if (creator !is Parcelable.Creator<*>) {
|
||||
expect.that(creator).isInstanceOf(Parcelable.Creator::class.java)
|
||||
return
|
||||
}
|
||||
|
||||
parcelTwo.setDataPosition(0)
|
||||
val parcelable = creator.createFromParcel(parcelTwo)
|
||||
if (parcelable::class.isSubclassOf(setterType)) {
|
||||
expect.withMessage(
|
||||
"${it.qualifiedName} which does not safely override writeToParcel " +
|
||||
"cannot contain a subclass CREATOR field"
|
||||
)
|
||||
.fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parcelOne.recycle()
|
||||
parcelTwo.recycle()
|
||||
}
|
||||
|
||||
private fun runAssertions(params: List<Param>, before: Parcelable, after: Parcelable) {
|
||||
params.forEach {
|
||||
val actual = it.getFunction(after)
|
||||
val expected = it.value()
|
||||
val equal = it.compare(actual, expected)
|
||||
expect.withMessage("${it.getFunctionName} was $actual, expected $expected")
|
||||
.that(equal)
|
||||
.isTrue()
|
||||
}
|
||||
|
||||
extraAssertions(before, after)
|
||||
|
||||
// TODO: Handle method overloads?
|
||||
val expectedFunctions = (getters.map { it.name }
|
||||
+ setters.map { it.name }
|
||||
- excludedMethods)
|
||||
.distinct()
|
||||
|
||||
val allTestedFunctions = params.flatMap {
|
||||
listOfNotNull(it.getFunctionName, it.setFunctionName)
|
||||
}
|
||||
expect.that(allTestedFunctions).containsExactlyElementsIn(expectedFunctions)
|
||||
}
|
||||
|
||||
open fun extraParams(): Collection<Param?> = emptyList()
|
||||
|
||||
open fun initialObject(): Parcelable = setterType.createInstance()
|
||||
|
||||
open fun extraAssertions(before: Parcelable, after: Parcelable) {}
|
||||
|
||||
open fun writeToParcel(parcel: Parcel, value: Parcelable) = value.writeToParcel(parcel, 0)
|
||||
|
||||
data class Param(
|
||||
val getFunctionName: String,
|
||||
val getFunction: (Any?) -> Any?,
|
||||
val setFunctionName: String?,
|
||||
val setFunction: (Array<Any?>) -> Unit,
|
||||
val value: () -> Any?,
|
||||
val compare: (Any?, Any?) -> Boolean = Objects::equals
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.android.server.pm.test.parsing.parcelling.java.TestSubWithCreator
|
||||
import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
|
||||
import org.junit.Test
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
/**
|
||||
* Verifies the failing side of [ParcelableCreatorValidTest]. The sole difference is the addition
|
||||
* of [TestSubWithCreator.CREATOR].
|
||||
*/
|
||||
@ExperimentalContracts
|
||||
class ParcelableCreatorInvalidTest :
|
||||
ParcelableComponentTest(TestSuperClass::class, TestSubWithCreator::class) {
|
||||
|
||||
override val defaultImpl = TestSubWithCreator()
|
||||
|
||||
override val creator = object : Parcelable.Creator<Parcelable> {
|
||||
override fun createFromParcel(source: Parcel) = TestSubWithCreator(source)
|
||||
override fun newArray(size: Int) = Array<TestSubWithCreator?>(size) { null }
|
||||
}
|
||||
|
||||
override val excludedMethods = listOf("writeSubToParcel")
|
||||
|
||||
override val baseParams = listOf(TestSuperClass::getSuperString)
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, value: Parcelable) {
|
||||
(value as TestSubWithCreator).writeSubToParcel(parcel, 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun parcellingSize() {
|
||||
super.parcellingSize()
|
||||
if (expect.hasFailures()) {
|
||||
// This is a hack to ignore an expected failure result. Doing it this way, rather than
|
||||
// adding a switch in the test itself, prevents it from accidentally passing through a
|
||||
// programming error.
|
||||
ignoreableExpect.ignore()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import com.android.server.pm.test.parsing.parcelling.java.TestSubWithoutCreator
|
||||
import com.android.server.pm.test.parsing.parcelling.java.TestSuperClass
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
/**
|
||||
* Tests the [Parcelable] CREATOR verification by using a mock object with known differences to
|
||||
* ensure that the method succeeds/fails.
|
||||
*/
|
||||
@ExperimentalContracts
|
||||
class ParcelableCreatorValidTest :
|
||||
ParcelableComponentTest(TestSuperClass::class, TestSubWithoutCreator::class) {
|
||||
|
||||
override val defaultImpl = TestSubWithoutCreator()
|
||||
|
||||
override val creator = object : Parcelable.Creator<Parcelable> {
|
||||
override fun createFromParcel(source: Parcel) = TestSubWithoutCreator(source)
|
||||
override fun newArray(size: Int) = Array<TestSubWithoutCreator?>(size) { null }
|
||||
}
|
||||
|
||||
override val excludedMethods = listOf("writeSubToParcel")
|
||||
|
||||
override val baseParams = listOf(TestSuperClass::getSuperString)
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, value: Parcelable) {
|
||||
(value as TestSubWithoutCreator).writeSubToParcel(parcel, 0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.parsing.component.ParsedActivity
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedActivityTest : ParsedMainComponentTest(ParsedActivity::class) {
|
||||
|
||||
override val defaultImpl = ParsedActivity()
|
||||
override val creator = ParsedActivity.CREATOR
|
||||
|
||||
override val mainComponentSubclassBaseParams = listOf(
|
||||
ParsedActivity::getPermission,
|
||||
ParsedActivity::getColorMode,
|
||||
ParsedActivity::getConfigChanges,
|
||||
ParsedActivity::getDocumentLaunchMode,
|
||||
ParsedActivity::getLaunchMode,
|
||||
ParsedActivity::getLockTaskLaunchMode,
|
||||
ParsedActivity::getMaxAspectRatio,
|
||||
ParsedActivity::getMaxRecents,
|
||||
ParsedActivity::getMinAspectRatio,
|
||||
ParsedActivity::getParentActivityName,
|
||||
ParsedActivity::getPersistableMode,
|
||||
ParsedActivity::getPrivateFlags,
|
||||
ParsedActivity::getRequestedVrComponent,
|
||||
ParsedActivity::getResizeMode,
|
||||
ParsedActivity::getRotationAnimation,
|
||||
ParsedActivity::getScreenOrientation,
|
||||
ParsedActivity::getSoftInputMode,
|
||||
ParsedActivity::getTargetActivity,
|
||||
ParsedActivity::getTaskAffinity,
|
||||
ParsedActivity::getTheme,
|
||||
ParsedActivity::getUiOptions,
|
||||
ParsedActivity::isSupportsSizeChanges,
|
||||
)
|
||||
|
||||
override fun mainComponentSubclassExtraParams() = listOf(
|
||||
getSetByValue(
|
||||
ParsedActivity::getWindowLayout,
|
||||
ParsedActivity::setWindowLayout,
|
||||
ActivityInfo.WindowLayout(1, 1f, 2, 1f, 3, 4, 5),
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
ActivityInfo.WindowLayout::width,
|
||||
ActivityInfo.WindowLayout::widthFraction,
|
||||
ActivityInfo.WindowLayout::height,
|
||||
ActivityInfo.WindowLayout::heightFraction,
|
||||
ActivityInfo.WindowLayout::gravity,
|
||||
ActivityInfo.WindowLayout::minWidth,
|
||||
ActivityInfo.WindowLayout::minHeight
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedAttribution
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedAttributionTest : ParcelableComponentTest(ParsedAttribution::class) {
|
||||
|
||||
override val defaultImpl = ParsedAttribution("", 0, emptyList())
|
||||
override val creator = ParsedAttribution.CREATOR
|
||||
|
||||
override val baseParams = listOf(
|
||||
ParsedAttribution::getTag,
|
||||
ParsedAttribution::getLabel,
|
||||
)
|
||||
|
||||
override fun extraParams() = listOf(
|
||||
getter(ParsedAttribution::getInheritFrom, listOf("testInheritFrom"))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.parsing.component.ParsedComponent
|
||||
import android.content.pm.parsing.component.ParsedIntentInfo
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction1
|
||||
|
||||
@ExperimentalContracts
|
||||
abstract class ParsedComponentTest(kClass: KClass<out Parcelable>) :
|
||||
ParcelableComponentTest(kClass) {
|
||||
|
||||
final override val excludedMethods
|
||||
get() = subclassExcludedMethods + listOf(
|
||||
// Method aliases/utilities
|
||||
"getClassName",
|
||||
"getComponentName",
|
||||
"setProperties" // Tested though addProperty
|
||||
)
|
||||
|
||||
open val subclassExcludedMethods: Collection<String> = emptyList()
|
||||
|
||||
final override val baseParams
|
||||
get() = subclassBaseParams + listOf(
|
||||
ParsedComponent::getBanner,
|
||||
ParsedComponent::getDescriptionRes,
|
||||
ParsedComponent::getFlags,
|
||||
ParsedComponent::getIcon,
|
||||
ParsedComponent::getLabelRes,
|
||||
ParsedComponent::getLogo,
|
||||
ParsedComponent::getName,
|
||||
ParsedComponent::getNonLocalizedLabel,
|
||||
ParsedComponent::getPackageName,
|
||||
)
|
||||
|
||||
abstract val subclassBaseParams: Collection<KFunction1<*, Any?>>
|
||||
|
||||
final override fun extraParams() = subclassExtraParams() + listOf(
|
||||
getSetByValue(
|
||||
ParsedComponent::getIntents,
|
||||
ParsedComponent::addIntent,
|
||||
"TestLabel",
|
||||
transformGet = { it.singleOrNull()?.nonLocalizedLabel },
|
||||
transformSet = { ParsedIntentInfo().setNonLocalizedLabel(it) },
|
||||
),
|
||||
getSetByValue(
|
||||
ParsedComponent::getProperties,
|
||||
ParsedComponent::addProperty,
|
||||
PackageManager.Property(
|
||||
"testPropertyName",
|
||||
"testPropertyValue",
|
||||
"testPropertyClassName",
|
||||
"testPropertyPackageName"
|
||||
),
|
||||
transformGet = { it["testPropertyName"] },
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
PackageManager.Property::getName,
|
||||
PackageManager.Property::getClassName,
|
||||
PackageManager.Property::getPackageName,
|
||||
PackageManager.Property::getString,
|
||||
)
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
ParsedComponent::getMetaData,
|
||||
ParsedComponent::setMetaData,
|
||||
"testBundleKey" to "testBundleValue",
|
||||
transformGet = { "testBundleKey" to it?.getString("testBundleKey") },
|
||||
transformSet = { Bundle().apply { putString(it.first, it.second) } }
|
||||
),
|
||||
)
|
||||
|
||||
open fun subclassExtraParams(): Collection<Param?> = emptyList()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedInstrumentation
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedInstrumentationTest : ParsedComponentTest(ParsedInstrumentation::class) {
|
||||
|
||||
override val defaultImpl = ParsedInstrumentation()
|
||||
override val creator = ParsedInstrumentation.CREATOR
|
||||
|
||||
override val subclassBaseParams = listOf(
|
||||
ParsedInstrumentation::getTargetPackage,
|
||||
ParsedInstrumentation::getTargetProcesses,
|
||||
ParsedInstrumentation::isFunctionalTest,
|
||||
ParsedInstrumentation::isHandleProfiling,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedIntentInfo
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
import android.os.PatternMatcher
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedIntentInfoTest : ParcelableComponentTest(ParsedIntentInfo::class) {
|
||||
|
||||
override val defaultImpl = ParsedIntentInfo()
|
||||
|
||||
override val creator = object : Parcelable.Creator<ParsedIntentInfo> {
|
||||
override fun createFromParcel(source: Parcel) = ParsedIntentInfo(source)
|
||||
override fun newArray(size: Int) = Array<ParsedIntentInfo?>(size) { null }
|
||||
}
|
||||
|
||||
override val excludedMethods = listOf(
|
||||
// Used to parcel
|
||||
"writeIntentInfoToParcel",
|
||||
// All remaining IntentFilter methods, which are out of scope
|
||||
"hasDataPath",
|
||||
"hasDataSchemeSpecificPart",
|
||||
"matchAction",
|
||||
"matchData",
|
||||
"actionsIterator",
|
||||
"addAction",
|
||||
"addCategory",
|
||||
"addDataAuthority",
|
||||
"addDataPath",
|
||||
"addDataScheme",
|
||||
"addDataSchemeSpecificPart",
|
||||
"addDataType",
|
||||
"addDynamicDataType",
|
||||
"addMimeGroup",
|
||||
"asPredicate",
|
||||
"asPredicateWithTypeResolution",
|
||||
"authoritiesIterator",
|
||||
"categoriesIterator",
|
||||
"clearDynamicDataTypes",
|
||||
"countActions",
|
||||
"countCategories",
|
||||
"countDataAuthorities",
|
||||
"countDataPaths",
|
||||
"countDataSchemeSpecificParts",
|
||||
"countDataSchemes",
|
||||
"countDataTypes",
|
||||
"countMimeGroups",
|
||||
"countStaticDataTypes",
|
||||
"dataTypes",
|
||||
"debugCheck",
|
||||
"dump",
|
||||
"dumpDebug",
|
||||
"getAction",
|
||||
"getAutoVerify",
|
||||
"getCategory",
|
||||
"getDataAuthority",
|
||||
"getDataPath",
|
||||
"getDataScheme",
|
||||
"getDataSchemeSpecificPart",
|
||||
"getDataType",
|
||||
"getHosts",
|
||||
"getHostsList",
|
||||
"getMimeGroup",
|
||||
"getOrder",
|
||||
"getPriority",
|
||||
"getVisibilityToInstantApp",
|
||||
"handleAllWebDataURI",
|
||||
"handlesWebUris",
|
||||
"hasAction",
|
||||
"hasCategory",
|
||||
"hasDataAuthority",
|
||||
"hasDataScheme",
|
||||
"hasDataType",
|
||||
"hasExactDataType",
|
||||
"hasExactDynamicDataType",
|
||||
"hasExactStaticDataType",
|
||||
"hasMimeGroup",
|
||||
"isExplicitlyVisibleToInstantApp",
|
||||
"isImplicitlyVisibleToInstantApp",
|
||||
"isVerified",
|
||||
"isVisibleToInstantApp",
|
||||
"match",
|
||||
"matchCategories",
|
||||
"matchDataAuthority",
|
||||
"mimeGroupsIterator",
|
||||
"needsVerification",
|
||||
"pathsIterator",
|
||||
"readFromXml",
|
||||
"schemeSpecificPartsIterator",
|
||||
"schemesIterator",
|
||||
"setAutoVerify",
|
||||
"setOrder",
|
||||
"setPriority",
|
||||
"setVerified",
|
||||
"setVisibilityToInstantApp",
|
||||
"typesIterator",
|
||||
"writeToXml",
|
||||
)
|
||||
|
||||
override val baseParams = listOf(
|
||||
ParsedIntentInfo::getIcon,
|
||||
ParsedIntentInfo::getLabelRes,
|
||||
ParsedIntentInfo::isHasDefault,
|
||||
ParsedIntentInfo::getNonLocalizedLabel,
|
||||
)
|
||||
|
||||
override fun initialObject() = ParsedIntentInfo().apply {
|
||||
addAction("test.ACTION")
|
||||
addDataAuthority("testAuthority", "404")
|
||||
addCategory("test.CATEGORY")
|
||||
addMimeGroup("testMime")
|
||||
addDataPath("testPath", PatternMatcher.PATTERN_LITERAL)
|
||||
}
|
||||
|
||||
override fun extraAssertions(before: Parcelable, after: Parcelable) {
|
||||
super.extraAssertions(before, after)
|
||||
after as ParsedIntentInfo
|
||||
expect.that(after.actionsIterator().asSequence().singleOrNull())
|
||||
.isEqualTo("test.ACTION")
|
||||
|
||||
val authority = after.authoritiesIterator().asSequence().singleOrNull()
|
||||
expect.that(authority?.host).isEqualTo("testAuthority")
|
||||
expect.that(authority?.port).isEqualTo(404)
|
||||
|
||||
expect.that(after.categoriesIterator().asSequence().singleOrNull())
|
||||
.isEqualTo("test.CATEGORY")
|
||||
expect.that(after.mimeGroupsIterator().asSequence().singleOrNull())
|
||||
.isEqualTo("testMime")
|
||||
expect.that(after.hasDataPath("testPath")).isTrue()
|
||||
}
|
||||
|
||||
override fun writeToParcel(parcel: Parcel, value: Parcelable) =
|
||||
ParsedIntentInfo.PARCELER.parcel(value as ParsedIntentInfo, parcel, 0)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedMainComponent
|
||||
import android.content.pm.parsing.component.ParsedService
|
||||
import android.os.Parcelable
|
||||
import java.util.Arrays
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KFunction1
|
||||
|
||||
@ExperimentalContracts
|
||||
abstract class ParsedMainComponentTest(kClass: KClass<out Parcelable>) :
|
||||
ParsedComponentTest(kClass) {
|
||||
|
||||
final override val subclassBaseParams
|
||||
get() = mainComponentSubclassBaseParams + listOf(
|
||||
ParsedMainComponent::getOrder,
|
||||
ParsedMainComponent::getProcessName,
|
||||
ParsedMainComponent::getSplitName,
|
||||
ParsedMainComponent::isDirectBootAware,
|
||||
ParsedMainComponent::isEnabled,
|
||||
ParsedMainComponent::isExported,
|
||||
)
|
||||
|
||||
abstract val mainComponentSubclassBaseParams: Collection<KFunction1<*, Any?>>
|
||||
|
||||
final override fun subclassExtraParams() = mainComponentSubclassExtraParams() + listOf(
|
||||
getSetByValue(
|
||||
ParsedService::getAttributionTags,
|
||||
ParsedService::setAttributionTags,
|
||||
arrayOf("testAttributionTag"),
|
||||
compare = Arrays::equals
|
||||
),
|
||||
)
|
||||
|
||||
open fun mainComponentSubclassExtraParams(): Collection<Param?> = emptyList()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedPermissionGroup
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedPermissionGroupTest : ParsedComponentTest(ParsedPermissionGroup::class) {
|
||||
|
||||
override val defaultImpl = ParsedPermissionGroup()
|
||||
override val creator = ParsedPermissionGroup.CREATOR
|
||||
|
||||
override val subclassBaseParams = listOf(
|
||||
ParsedPermissionGroup::getRequestDetailResourceId,
|
||||
ParsedPermissionGroup::getBackgroundRequestDetailResourceId,
|
||||
ParsedPermissionGroup::getBackgroundRequestResourceId,
|
||||
ParsedPermissionGroup::getRequestRes,
|
||||
ParsedPermissionGroup::getPriority,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedPermission
|
||||
import android.content.pm.parsing.component.ParsedPermissionGroup
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedPermissionTest : ParsedComponentTest(ParsedPermission::class) {
|
||||
|
||||
override val defaultImpl = ParsedPermission()
|
||||
override val creator = ParsedPermission.CREATOR
|
||||
|
||||
override val subclassExcludedMethods = listOf(
|
||||
// Utility methods
|
||||
"isAppOp",
|
||||
"isRuntime",
|
||||
"getProtection",
|
||||
"getProtectionFlags",
|
||||
"calculateFootprint",
|
||||
"setKnownCert", // Tested through setKnownCerts
|
||||
)
|
||||
override val subclassBaseParams = listOf(
|
||||
ParsedPermission::getBackgroundPermission,
|
||||
ParsedPermission::getGroup,
|
||||
ParsedPermission::getRequestRes,
|
||||
ParsedPermission::getProtectionLevel,
|
||||
ParsedPermission::isTree,
|
||||
)
|
||||
|
||||
override fun subclassExtraParams() = listOf(
|
||||
getter(ParsedPermission::getKnownCerts, setOf("testCert")),
|
||||
getSetByValue(
|
||||
ParsedPermission::getParsedPermissionGroup,
|
||||
ParsedPermission::setParsedPermissionGroup,
|
||||
ParsedPermissionGroup().apply { name = "test.permission.group" },
|
||||
compare = { first, second -> equalBy(first, second, ParsedPermissionGroup::getName) }
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedProcess
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedProcessTest : ParcelableComponentTest(ParsedProcess::class) {
|
||||
|
||||
override val defaultImpl = ParsedProcess()
|
||||
override val creator = ParsedProcess.CREATOR
|
||||
|
||||
override val excludedMethods = listOf(
|
||||
// Copying method
|
||||
"addStateFrom",
|
||||
)
|
||||
|
||||
override val baseParams = listOf(
|
||||
ParsedProcess::getName,
|
||||
ParsedProcess::getGwpAsanMode,
|
||||
ParsedProcess::getMemtagMode,
|
||||
ParsedProcess::getNativeHeapZeroInitialized,
|
||||
)
|
||||
|
||||
override fun extraParams() = listOf(
|
||||
getter(ParsedProcess::getDeniedPermissions, setOf("testDeniedPermission"))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.PathPermission
|
||||
import android.content.pm.parsing.component.ParsedProvider
|
||||
import android.os.PatternMatcher
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedProviderTest : ParsedMainComponentTest(ParsedProvider::class) {
|
||||
|
||||
override val defaultImpl = ParsedProvider()
|
||||
override val creator = ParsedProvider.CREATOR
|
||||
|
||||
override val mainComponentSubclassBaseParams = listOf(
|
||||
ParsedProvider::getAuthority,
|
||||
ParsedProvider::isSyncable,
|
||||
ParsedProvider::getReadPermission,
|
||||
ParsedProvider::getWritePermission,
|
||||
ParsedProvider::isGrantUriPermissions,
|
||||
ParsedProvider::isForceUriPermissions,
|
||||
ParsedProvider::isMultiProcess,
|
||||
ParsedProvider::getInitOrder,
|
||||
)
|
||||
|
||||
override fun mainComponentSubclassExtraParams() = listOf(
|
||||
getSetByValue(
|
||||
ParsedProvider::getUriPermissionPatterns,
|
||||
ParsedProvider::setUriPermissionPatterns,
|
||||
PatternMatcher("testPattern", PatternMatcher.PATTERN_LITERAL),
|
||||
transformGet = { it?.singleOrNull() },
|
||||
transformSet = { arrayOf(it) },
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
PatternMatcher::getPath,
|
||||
PatternMatcher::getType
|
||||
)
|
||||
}
|
||||
),
|
||||
getSetByValue(
|
||||
ParsedProvider::getPathPermissions,
|
||||
ParsedProvider::setPathPermissions,
|
||||
PathPermission(
|
||||
"testPermissionPattern",
|
||||
PatternMatcher.PATTERN_LITERAL,
|
||||
"test.READ_PERMISSION",
|
||||
"test.WRITE_PERMISSION"
|
||||
),
|
||||
transformGet = { it?.singleOrNull() },
|
||||
transformSet = { arrayOf(it) },
|
||||
compare = { first, second ->
|
||||
equalBy(
|
||||
first, second,
|
||||
PatternMatcher::getPath,
|
||||
PatternMatcher::getType,
|
||||
PathPermission::getReadPermission,
|
||||
PathPermission::getWritePermission,
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedService
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedServiceTest : ParsedMainComponentTest(ParsedService::class) {
|
||||
|
||||
override val defaultImpl = ParsedService()
|
||||
override val creator = ParsedService.CREATOR
|
||||
|
||||
override val mainComponentSubclassBaseParams = listOf(
|
||||
ParsedService::getForegroundServiceType,
|
||||
ParsedService::getPermission,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling
|
||||
|
||||
import android.content.pm.parsing.component.ParsedUsesPermission
|
||||
import android.os.Parcelable
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
|
||||
@ExperimentalContracts
|
||||
class ParsedUsesPermissionTest : ParcelableComponentTest(ParsedUsesPermission::class) {
|
||||
|
||||
override val defaultImpl = ParsedUsesPermission("", 0)
|
||||
override val creator = ParsedUsesPermission.CREATOR
|
||||
|
||||
override val baseParams = listOf(
|
||||
ParsedUsesPermission::getName,
|
||||
ParsedUsesPermission::getUsesPermissionFlags
|
||||
)
|
||||
|
||||
override fun initialObject() = ParsedUsesPermission("", 0)
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling.java;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class TestSubWithCreator extends TestSuperClass {
|
||||
|
||||
@NonNull
|
||||
public static final Parcelable.Creator<TestSubWithCreator> CREATOR =
|
||||
new Parcelable.Creator<TestSubWithCreator>() {
|
||||
@Override
|
||||
public TestSubWithCreator createFromParcel(Parcel source) {
|
||||
return new TestSubWithCreator(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestSubWithCreator[] newArray(int size) {
|
||||
return new TestSubWithCreator[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
private String subString;
|
||||
|
||||
public TestSubWithCreator() {
|
||||
}
|
||||
|
||||
public TestSubWithCreator(@NonNull Parcel in) {
|
||||
super(in);
|
||||
subString = in.readString();
|
||||
}
|
||||
|
||||
public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
|
||||
super.writeToParcel(parcel, flags);
|
||||
parcel.writeString(subString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling.java;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public class TestSubWithoutCreator extends TestSuperClass {
|
||||
|
||||
@Nullable
|
||||
private String subString;
|
||||
|
||||
public TestSubWithoutCreator() {
|
||||
}
|
||||
|
||||
public TestSubWithoutCreator(@NonNull Parcel in) {
|
||||
super(in);
|
||||
subString = in.readString();
|
||||
}
|
||||
|
||||
public void writeSubToParcel(@NonNull Parcel parcel, int flags) {
|
||||
super.writeToParcel(parcel, flags);
|
||||
parcel.writeString(subString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.parsing.parcelling.java;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.util.DataClass;
|
||||
|
||||
@DataClass(genGetters = true, genSetters = true, genBuilder = false, genAidl = false,
|
||||
genParcelable = true, genConstructor = false)
|
||||
public class TestSuperClass implements Parcelable {
|
||||
|
||||
@Nullable
|
||||
private String superString;
|
||||
|
||||
public TestSuperClass() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Code below generated by codegen v1.0.23.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
//
|
||||
// To regenerate run:
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java
|
||||
//
|
||||
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||||
// Settings > Editor > Code Style > Formatter Control
|
||||
//@formatter:off
|
||||
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @Nullable String getSuperString() {
|
||||
return superString;
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull TestSuperClass setSuperString(@NonNull String value) {
|
||||
superString = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
|
||||
// You can override field parcelling by defining methods like:
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
|
||||
byte flg = 0;
|
||||
if (superString != null) flg |= 0x1;
|
||||
dest.writeByte(flg);
|
||||
if (superString != null) dest.writeString(superString);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public int describeContents() { return 0; }
|
||||
|
||||
/** @hide */
|
||||
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||||
@DataClass.Generated.Member
|
||||
protected TestSuperClass(@NonNull android.os.Parcel in) {
|
||||
// You can override field unparcelling by defining methods like:
|
||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||
|
||||
byte flg = in.readByte();
|
||||
String _superString = (flg & 0x1) == 0 ? null : in.readString();
|
||||
|
||||
this.superString = _superString;
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public static final @NonNull Parcelable.Creator<TestSuperClass> CREATOR
|
||||
= new Parcelable.Creator<TestSuperClass>() {
|
||||
@Override
|
||||
public TestSuperClass[] newArray(int size) {
|
||||
return new TestSuperClass[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestSuperClass createFromParcel(@NonNull android.os.Parcel in) {
|
||||
return new TestSuperClass(in);
|
||||
}
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1624381019144L,
|
||||
codegenVersion = "1.0.23",
|
||||
sourceFile = "frameworks/base/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/java/TestSuperClass.java",
|
||||
inputSignatures = "private @android.annotation.Nullable java.lang.String superString\nclass TestSuperClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=true, genBuilder=false, genAidl=false, genParcelable=true, genConstructor=false)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
//@formatter:on
|
||||
// End of generated code
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.test.util
|
||||
|
||||
import com.google.common.truth.Expect
|
||||
import org.junit.rules.TestRule
|
||||
import org.junit.runner.Description
|
||||
import org.junit.runners.model.Statement
|
||||
|
||||
/**
|
||||
* Wrapper for [Expect] which supports ignoring any failures. This should be used with caution, but
|
||||
* it allows a base test to be written which doesn't switch success/failure in the test itself,
|
||||
* preventing any logic errors from causing the test to accidentally succeed.
|
||||
*/
|
||||
internal class IgnoreableExpect : TestRule {
|
||||
|
||||
val expect = Expect.create()
|
||||
|
||||
private var ignore = false
|
||||
|
||||
override fun apply(base: Statement?, description: Description?): Statement {
|
||||
return object : Statement() {
|
||||
override fun evaluate() {
|
||||
ignore = false
|
||||
try {
|
||||
expect.apply(base, description).evaluate()
|
||||
} catch (t: Throwable) {
|
||||
if (!ignore) {
|
||||
throw t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ignore() {
|
||||
ignore = true
|
||||
}
|
||||
}
|
||||
@@ -949,7 +949,7 @@ public class PackageParserTest {
|
||||
.addConfigPreference(new ConfigurationInfo())
|
||||
.addReqFeature(new FeatureInfo())
|
||||
.addFeatureGroup(new FeatureGroupInfo())
|
||||
.setCompileSdkVersionCodename("foo23")
|
||||
.setCompileSdkVersionCodeName("foo23")
|
||||
.setCompileSdkVersion(100)
|
||||
.setOverlayCategory("foo24")
|
||||
.setOverlayIsStatic(true)
|
||||
|
||||
Reference in New Issue
Block a user