blob: 5a428414a97080fc51e33db504a7119fbbab76f6 [file] [log] [blame]
Calin Juravle6ea5ace2016-12-01 17:53:07 +00001/*
2 * Copyright (C) 2016 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
17package com.android.server.pm.dex;
18
19import android.os.Build;
20import android.support.test.filters.SmallTest;
21import android.support.test.runner.AndroidJUnit4;
22import dalvik.system.VMRuntime;
23
24import org.junit.Before;
25import org.junit.Test;
26import org.junit.runner.RunWith;
27
28import java.io.IOException;
29import java.io.StringReader;
30import java.io.StringWriter;
31import java.util.Arrays;
32import java.util.HashMap;
33import java.util.HashSet;
34import java.util.Map;
35import java.util.Set;
36
37import static org.junit.Assert.assertEquals;
38import static org.junit.Assert.assertFalse;
39import static org.junit.Assert.assertNotNull;
40import static org.junit.Assert.assertNull;
41import static org.junit.Assert.assertTrue;
42import static org.junit.Assert.fail;
43
44import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
45import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
46
47@RunWith(AndroidJUnit4.class)
48@SmallTest
49public class PackageDexUsageTests {
50 private PackageDexUsage mPackageDexUsage;
51
52 private TestData mFooBaseUser0;
53 private TestData mFooSplit1User0;
54 private TestData mFooSplit2UsedByOtherApps0;
55 private TestData mFooSecondary1User0;
56 private TestData mFooSecondary1User1;
57 private TestData mFooSecondary2UsedByOtherApps0;
58 private TestData mInvalidIsa;
59
60 private TestData mBarBaseUser0;
61 private TestData mBarSecondary1User0;
62 private TestData mBarSecondary2User1;
63
64 @Before
65 public void setup() {
66 mPackageDexUsage = new PackageDexUsage();
67
68 String fooPackageName = "com.google.foo";
69 String fooCodeDir = "/data/app/com.google.foo/";
70 String fooDataDir = "/data/user/0/com.google.foo/";
71
72 String isa = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
73
74 mFooBaseUser0 = new TestData(fooPackageName,
75 fooCodeDir + "base.apk", 0, isa, false, true);
76
77 mFooSplit1User0 = new TestData(fooPackageName,
78 fooCodeDir + "split-1.apk", 0, isa, false, true);
79
80 mFooSplit2UsedByOtherApps0 = new TestData(fooPackageName,
81 fooCodeDir + "split-2.apk", 0, isa, true, true);
82
83 mFooSecondary1User0 = new TestData(fooPackageName,
84 fooDataDir + "sec-1.dex", 0, isa, false, false);
85
86 mFooSecondary1User1 = new TestData(fooPackageName,
87 fooDataDir + "sec-1.dex", 1, isa, false, false);
88
89 mFooSecondary2UsedByOtherApps0 = new TestData(fooPackageName,
90 fooDataDir + "sec-2.dex", 0, isa, true, false);
91
92 mInvalidIsa = new TestData(fooPackageName,
93 fooCodeDir + "base.apk", 0, "INVALID_ISA", false, true);
94
95 String barPackageName = "com.google.bar";
96 String barCodeDir = "/data/app/com.google.bar/";
97 String barDataDir = "/data/user/0/com.google.bar/";
98 String barDataDir1 = "/data/user/1/com.google.bar/";
99
100 mBarBaseUser0 = new TestData(barPackageName,
101 barCodeDir + "base.apk", 0, isa, false, true);
102 mBarSecondary1User0 = new TestData(barPackageName,
103 barDataDir + "sec-1.dex", 0, isa, false, false);
104 mBarSecondary2User1 = new TestData(barPackageName,
105 barDataDir1 + "sec-2.dex", 1, isa, false, false);
106 }
107
108 @Test
109 public void testRecordPrimary() {
110 // Assert new information.
111 assertTrue(record(mFooBaseUser0));
112
113 assertPackageDexUsage(mFooBaseUser0);
114 writeAndReadBack();
115 assertPackageDexUsage(mFooBaseUser0);
116 }
117
118 @Test
119 public void testRecordSplit() {
120 // Assert new information.
121 assertTrue(record(mFooSplit1User0));
122
123 assertPackageDexUsage(mFooSplit1User0);
124 writeAndReadBack();
125 assertPackageDexUsage(mFooSplit1User0);
126 }
127
128 @Test
129 public void testRecordSplitPrimarySequence() {
130 // Assert new information.
131 assertTrue(record(mFooBaseUser0));
132 // Assert no new information.
133 assertFalse(record(mFooSplit1User0));
134
135 assertPackageDexUsage(mFooBaseUser0);
136 writeAndReadBack();
137 assertPackageDexUsage(mFooBaseUser0);
138
139 // Write Split2 which is used by other apps.
140 // Assert new information.
141 assertTrue(record(mFooSplit2UsedByOtherApps0));
142 assertPackageDexUsage(mFooSplit2UsedByOtherApps0);
143 writeAndReadBack();
144 assertPackageDexUsage(mFooSplit2UsedByOtherApps0);
145 }
146
147 @Test
148 public void testRecordSecondary() {
149 assertTrue(record(mFooSecondary1User0));
150
151 assertPackageDexUsage(null, mFooSecondary1User0);
152 writeAndReadBack();
153 assertPackageDexUsage(null, mFooSecondary1User0);
154
155 // Recording again does not add more data.
156 assertFalse(record(mFooSecondary1User0));
157 assertPackageDexUsage(null, mFooSecondary1User0);
158 }
159
160 @Test
161 public void testRecordBaseAndSecondarySequence() {
162 // Write split.
163 assertTrue(record(mFooSplit2UsedByOtherApps0));
164 // Write secondary.
165 assertTrue(record(mFooSecondary1User0));
166
167 // Check.
168 assertPackageDexUsage(mFooSplit2UsedByOtherApps0, mFooSecondary1User0);
169 writeAndReadBack();
170 assertPackageDexUsage(mFooSplit2UsedByOtherApps0, mFooSecondary1User0);
171
172 // Write another secondary.
173 assertTrue(record(mFooSecondary2UsedByOtherApps0));
174
175 // Check.
176 assertPackageDexUsage(
177 mFooSplit2UsedByOtherApps0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
178 writeAndReadBack();
179 assertPackageDexUsage(
180 mFooSplit2UsedByOtherApps0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
181 }
182
183 @Test
184 public void testMultiplePackages() {
185 assertTrue(record(mFooBaseUser0));
186 assertTrue(record(mFooSecondary1User0));
187 assertTrue(record(mFooSecondary2UsedByOtherApps0));
188 assertTrue(record(mBarBaseUser0));
189 assertTrue(record(mBarSecondary1User0));
190 assertTrue(record(mBarSecondary2User1));
191
192 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
193 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
194 writeAndReadBack();
195 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
196 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
197 }
198
199 @Test
200 public void testPackageNotFound() {
201 assertNull(mPackageDexUsage.getPackageUseInfo("missing.package"));
202 }
203
204 @Test
205 public void testAttemptToChangeOwner() {
206 assertTrue(record(mFooSecondary1User0));
207 try {
208 record(mFooSecondary1User1);
209 fail("Expected exception");
210 } catch (IllegalArgumentException e) {
211 // expected
212 }
213 }
214
215 @Test
216 public void testInvalidIsa() {
217 try {
218 record(mInvalidIsa);
219 fail("Expected exception");
220 } catch (IllegalArgumentException e) {
221 // expected
222 }
223 }
224
225 @Test
226 public void testReadWriteEmtpy() {
227 // Expect no exceptions when writing/reading without data.
228 writeAndReadBack();
229 }
230
231 @Test
232 public void testSyncData() {
233 // Write some records.
234 assertTrue(record(mFooBaseUser0));
235 assertTrue(record(mFooSecondary1User0));
236 assertTrue(record(mFooSecondary2UsedByOtherApps0));
237 assertTrue(record(mBarBaseUser0));
238 assertTrue(record(mBarSecondary1User0));
239 assertTrue(record(mBarSecondary2User1));
240
241 // Verify all is good.
242 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
243 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
244 writeAndReadBack();
245 assertPackageDexUsage(mFooBaseUser0, mFooSecondary1User0, mFooSecondary2UsedByOtherApps0);
246 assertPackageDexUsage(mBarBaseUser0, mBarSecondary1User0, mBarSecondary2User1);
247
248 // Simulate that only user 1 is available.
249 Map<String, Set<Integer>> packageToUsersMap = new HashMap<>();
250 packageToUsersMap.put(mBarSecondary2User1.mPackageName,
251 new HashSet<>(Arrays.asList(mBarSecondary2User1.mOwnerUserId)));
252 mPackageDexUsage.syncData(packageToUsersMap);
253
254 // Assert that only user 1 files are there.
255 assertPackageDexUsage(mBarBaseUser0, mBarSecondary2User1);
256 assertNull(mPackageDexUsage.getPackageUseInfo(mFooBaseUser0.mPackageName));
257 }
258
259 private void assertPackageDexUsage(TestData primary, TestData... secondaries) {
260 String packageName = primary == null ? secondaries[0].mPackageName : primary.mPackageName;
261 boolean primaryUsedByOtherApps = primary == null ? false : primary.mUsedByOtherApps;
262 PackageUseInfo pInfo = mPackageDexUsage.getPackageUseInfo(packageName);
263
264 // Check package use info
265 assertNotNull(pInfo);
266 assertEquals(primaryUsedByOtherApps, pInfo.isUsedByOtherApps());
267 Map<String, DexUseInfo> dexUseInfoMap = pInfo.getDexUseInfoMap();
268 assertEquals(secondaries.length, dexUseInfoMap.size());
269
270 // Check dex use info
271 for (TestData testData : secondaries) {
272 DexUseInfo dInfo = dexUseInfoMap.get(testData.mDexFile);
273 assertNotNull(dInfo);
274 assertEquals(testData.mUsedByOtherApps, dInfo.isUsedByOtherApps());
275 assertEquals(testData.mOwnerUserId, dInfo.getOwnerUserId());
276 assertEquals(1, dInfo.getLoaderIsas().size());
277 assertTrue(dInfo.getLoaderIsas().contains(testData.mLoaderIsa));
278 }
279 }
280
281 private boolean record(TestData testData) {
282 return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile,
283 testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps,
284 testData.mPrimaryOrSplit);
285 }
286
287 private void writeAndReadBack() {
288 try {
289 StringWriter writer = new StringWriter();
290 mPackageDexUsage.write(writer);
291
292 mPackageDexUsage = new PackageDexUsage();
293 mPackageDexUsage.read(new StringReader(writer.toString()));
294 } catch (IOException e) {
295 fail("Unexpected IOException: " + e.getMessage());
296 }
297 }
298
299 private static class TestData {
300 private final String mPackageName;
301 private final String mDexFile;
302 private final int mOwnerUserId;
303 private final String mLoaderIsa;
304 private final boolean mUsedByOtherApps;
305 private final boolean mPrimaryOrSplit;
306
307 private TestData(String packageName, String dexFile, int ownerUserId,
308 String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit) {
309 mPackageName = packageName;
310 mDexFile = dexFile;
311 mOwnerUserId = ownerUserId;
312 mLoaderIsa = loaderIsa;
313 mUsedByOtherApps = isUsedByOtherApps;
314 mPrimaryOrSplit = primaryOrSplit;
315 }
316
317 }
318}