1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm.test
18 
19 import com.android.internal.util.test.SystemPreparer
20 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
21 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
22 import com.google.common.truth.Truth.assertThat
23 import org.junit.After
24 import org.junit.Before
25 import org.junit.ClassRule
26 import org.junit.Rule
27 import org.junit.Test
28 import org.junit.rules.RuleChain
29 import org.junit.rules.TemporaryFolder
30 import org.junit.runner.RunWith
31 
32 @RunWith(DeviceJUnit4ClassRunner::class)
33 class OriginalPackageMigrationTest : BaseHostJUnit4Test() {
34 
35     companion object {
36         private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
37         private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk"
38         private const val VERSION_TWO = "PackageManagerTestAppVersion2.apk"
39         private const val VERSION_THREE = "PackageManagerTestAppVersion3.apk"
40         private const val NEW_PKG = "PackageManagerTestAppOriginalOverride.apk"
41 
42         @get:ClassRule
43         val deviceRebootRule = SystemPreparer.TestRuleDelegate(true)
44     }
45 
46     private val tempFolder = TemporaryFolder()
47     private val preparer: SystemPreparer = SystemPreparer(tempFolder,
48             SystemPreparer.RebootStrategy.FULL, deviceRebootRule) { this.device }
49 
50     @Rule
51     @JvmField
52     val rules = RuleChain.outerRule(tempFolder).around(preparer)!!
53 
54     @Before
55     @After
56     fun deleteApkFolders() {
57         preparer.deleteApkFolders(Partition.SYSTEM, VERSION_ONE, VERSION_TWO, VERSION_THREE,
58                 NEW_PKG)
59                 .reboot()
60     }
61 
62     @Test
63     fun lowerVersion() {
64         runForApk(VERSION_ONE)
65     }
66 
67     @Test
68     fun sameVersion() {
69         runForApk(VERSION_TWO)
70     }
71 
72     @Test
73     fun higherVersion() {
74         runForApk(VERSION_THREE)
75     }
76 
77     // A bug was found where renamed the package during parsing was leading to an invalid version
78     // code check at scan time. A lower version package was being dropped after reboot. To test
79     // this, the override APK is defined as versionCode 2 and the original package is given
80     // versionCode 1, 2, and 3 from the other methods.
81     private fun runForApk(apk: String) {
82         preparer.pushApk(apk, Partition.SYSTEM)
83                 .reboot()
84 
85         assertCodePath(apk)
86 
87         // Ensure data is preserved by writing to the original dataDir
88         val file = tempFolder.newFile().apply { writeText("Test") }
89         device.pushFile(file, "${HostUtils.getDataDir(device, TEST_PKG_NAME)}/files/test.txt")
90 
91         preparer.deleteApkFolders(Partition.SYSTEM, apk)
92                 .pushApk(NEW_PKG, Partition.SYSTEM)
93                 .reboot()
94 
95         assertCodePath(NEW_PKG)
96 
97         // And then reading the data contents back
98         assertThat(device.pullFileContents(
99                 "${HostUtils.getDataDir(device, TEST_PKG_NAME)}/files/test.txt"))
100                 .isEqualTo("Test")
101     }
102 
103     private fun assertCodePath(apk: String) {
104         assertThat(HostUtils.getCodePaths(device, TEST_PKG_NAME))
105                 .containsExactly(HostUtils.makePathForApk(apk, Partition.SYSTEM).parent.toString())
106     }
107 }
108