PackageDexUsageTests.java revision 99dd37b3c5262910150ef955d16a33d32da264dd
1/* 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 @Test 260 public void testRemovePackage() { 261 // Record Bar secondaries for two different users. 262 assertTrue(record(mBarSecondary1User0)); 263 assertTrue(record(mBarSecondary2User1)); 264 265 // Remove the package. 266 assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName)); 267 // Assert that we can't find the package anymore. 268 assertNull(mPackageDexUsage.getPackageUseInfo(mBarSecondary1User0.mPackageName)); 269 } 270 271 @Test 272 public void testRemoveNonexistentPackage() { 273 // Record Bar secondaries for two different users. 274 assertTrue(record(mBarSecondary1User0)); 275 276 // Remove the package. 277 assertTrue(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName)); 278 // Remove the package again. It should return false because the package no longer 279 // has a record in the use info. 280 assertFalse(mPackageDexUsage.removePackage(mBarSecondary1User0.mPackageName)); 281 } 282 283 @Test 284 public void testRemoveUserPackage() { 285 // Record Bar secondaries for two different users. 286 assertTrue(record(mBarSecondary1User0)); 287 assertTrue(record(mBarSecondary2User1)); 288 289 // Remove user 0 files. 290 assertTrue(mPackageDexUsage.removeUserPackage(mBarSecondary1User0.mPackageName, 291 mBarSecondary1User0.mOwnerUserId)); 292 // Assert that only user 1 files are there. 293 assertPackageDexUsage(null, mBarSecondary2User1); 294 } 295 296 @Test 297 public void testRemoveDexFile() { 298 // Record Bar secondaries for two different users. 299 assertTrue(record(mBarSecondary1User0)); 300 assertTrue(record(mBarSecondary2User1)); 301 302 // Remove mBarSecondary1User0 file. 303 assertTrue(mPackageDexUsage.removeDexFile(mBarSecondary1User0.mPackageName, 304 mBarSecondary1User0.mDexFile, mBarSecondary1User0.mOwnerUserId)); 305 // Assert that only user 1 files are there. 306 assertPackageDexUsage(null, mBarSecondary2User1); 307 } 308 309 @Test 310 public void testClearUsedByOtherApps() { 311 // Write a package which is used by other apps. 312 assertTrue(record(mFooSplit2UsedByOtherApps0)); 313 assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName)); 314 315 // Check that the package is no longer used by other apps. 316 TestData noLongerUsedByOtherApps = new TestData( 317 mFooSplit2UsedByOtherApps0.mPackageName, 318 mFooSplit2UsedByOtherApps0.mDexFile, 319 mFooSplit2UsedByOtherApps0.mOwnerUserId, 320 mFooSplit2UsedByOtherApps0.mLoaderIsa, 321 /*mIsUsedByOtherApps*/false, 322 mFooSplit2UsedByOtherApps0.mPrimaryOrSplit); 323 assertPackageDexUsage(noLongerUsedByOtherApps); 324 } 325 326 @Test 327 public void testClearUsedByOtherAppsNonexistent() { 328 // Write a package which is used by other apps. 329 assertTrue(record(mFooSplit2UsedByOtherApps0)); 330 assertTrue(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName)); 331 // Clearing again should return false as there should be no update on the use info. 332 assertFalse(mPackageDexUsage.clearUsedByOtherApps(mFooSplit2UsedByOtherApps0.mPackageName)); 333 } 334 335 private void assertPackageDexUsage(TestData primary, TestData... secondaries) { 336 String packageName = primary == null ? secondaries[0].mPackageName : primary.mPackageName; 337 boolean primaryUsedByOtherApps = primary == null ? false : primary.mUsedByOtherApps; 338 PackageUseInfo pInfo = mPackageDexUsage.getPackageUseInfo(packageName); 339 340 // Check package use info 341 assertNotNull(pInfo); 342 assertEquals(primaryUsedByOtherApps, pInfo.isUsedByOtherApps()); 343 Map<String, DexUseInfo> dexUseInfoMap = pInfo.getDexUseInfoMap(); 344 assertEquals(secondaries.length, dexUseInfoMap.size()); 345 346 // Check dex use info 347 for (TestData testData : secondaries) { 348 DexUseInfo dInfo = dexUseInfoMap.get(testData.mDexFile); 349 assertNotNull(dInfo); 350 assertEquals(testData.mUsedByOtherApps, dInfo.isUsedByOtherApps()); 351 assertEquals(testData.mOwnerUserId, dInfo.getOwnerUserId()); 352 assertEquals(1, dInfo.getLoaderIsas().size()); 353 assertTrue(dInfo.getLoaderIsas().contains(testData.mLoaderIsa)); 354 } 355 } 356 357 private boolean record(TestData testData) { 358 return mPackageDexUsage.record(testData.mPackageName, testData.mDexFile, 359 testData.mOwnerUserId, testData.mLoaderIsa, testData.mUsedByOtherApps, 360 testData.mPrimaryOrSplit); 361 } 362 363 private void writeAndReadBack() { 364 try { 365 StringWriter writer = new StringWriter(); 366 mPackageDexUsage.write(writer); 367 368 mPackageDexUsage = new PackageDexUsage(); 369 mPackageDexUsage.read(new StringReader(writer.toString())); 370 } catch (IOException e) { 371 fail("Unexpected IOException: " + e.getMessage()); 372 } 373 } 374 375 private static class TestData { 376 private final String mPackageName; 377 private final String mDexFile; 378 private final int mOwnerUserId; 379 private final String mLoaderIsa; 380 private final boolean mUsedByOtherApps; 381 private final boolean mPrimaryOrSplit; 382 383 private TestData(String packageName, String dexFile, int ownerUserId, 384 String loaderIsa, boolean isUsedByOtherApps, boolean primaryOrSplit) { 385 mPackageName = packageName; 386 mDexFile = dexFile; 387 mOwnerUserId = ownerUserId; 388 mLoaderIsa = loaderIsa; 389 mUsedByOtherApps = isUsedByOtherApps; 390 mPrimaryOrSplit = primaryOrSplit; 391 } 392 393 } 394} 395