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 17 package com.android.server.storage; 18 19 import android.content.pm.PackageStats; 20 import android.test.AndroidTestCase; 21 import android.util.ArraySet; 22 import libcore.io.IoUtils; 23 import org.json.JSONArray; 24 import org.json.JSONObject; 25 import org.junit.Before; 26 import org.junit.Rule; 27 import org.junit.Test; 28 import org.junit.rules.TemporaryFolder; 29 import org.junit.runner.RunWith; 30 import org.junit.runners.JUnit4; 31 32 import java.io.File; 33 import java.util.ArrayList; 34 35 import static com.google.common.truth.Truth.assertThat; 36 37 @RunWith(JUnit4.class) 38 public class DiskStatsFileLoggerTest extends AndroidTestCase { 39 @Rule public TemporaryFolder temporaryFolder; 40 public FileCollector.MeasurementResult mMainResult; 41 public FileCollector.MeasurementResult mDownloadsResult; 42 private ArrayList<PackageStats> mPackages; 43 private File mOutputFile; 44 45 @Before 46 public void setUp() throws Exception { 47 super.setUp(); 48 temporaryFolder = new TemporaryFolder(); 49 temporaryFolder.create(); 50 mOutputFile = temporaryFolder.newFile(); 51 mMainResult = new FileCollector.MeasurementResult(); 52 mDownloadsResult = new FileCollector.MeasurementResult(); 53 mPackages = new ArrayList<>(); 54 } 55 56 @Test 57 public void testEmptyStorage() throws Exception { 58 DiskStatsFileLogger logger = new DiskStatsFileLogger( 59 mMainResult, mDownloadsResult,mPackages, 0L); 60 61 logger.dumpToFile(mOutputFile); 62 63 JSONObject output = getOutputFileAsJson(); 64 assertThat(output.getLong(DiskStatsFileLogger.PHOTOS_KEY)).isEqualTo(0L); 65 assertThat(output.getLong(DiskStatsFileLogger.VIDEOS_KEY)).isEqualTo(0L); 66 assertThat(output.getLong(DiskStatsFileLogger.AUDIO_KEY)).isEqualTo(0L); 67 assertThat(output.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(0L); 68 assertThat(output.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(0L); 69 assertThat(output.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(0L); 70 assertThat(output.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(0L); 71 assertThat(output.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(0L); 72 assertThat( 73 output.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(0L); 74 assertThat(output.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(0L); 75 assertThat(output.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(0L); 76 } 77 78 @Test 79 public void testMeasurementResultsReported() throws Exception { 80 mMainResult.audioSize = 1; 81 mMainResult.imagesSize = 10; 82 mMainResult.miscSize = 100; 83 mDownloadsResult.miscSize = 1000; 84 DiskStatsFileLogger logger = new DiskStatsFileLogger( 85 mMainResult, mDownloadsResult,mPackages, 3L); 86 87 logger.dumpToFile(mOutputFile); 88 89 JSONObject output = getOutputFileAsJson(); 90 assertThat(output.getLong(DiskStatsFileLogger.AUDIO_KEY)).isEqualTo(1L); 91 assertThat(output.getLong(DiskStatsFileLogger.PHOTOS_KEY)).isEqualTo(10L); 92 assertThat(output.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(100L); 93 assertThat(output.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(1000L); 94 assertThat(output.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(3L); 95 } 96 97 @Test 98 public void testAppsReported() throws Exception { 99 PackageStats firstPackage = new PackageStats("com.test.app"); 100 firstPackage.codeSize = 100; 101 firstPackage.dataSize = 1000; 102 firstPackage.cacheSize = 20; 103 mPackages.add(firstPackage); 104 105 PackageStats secondPackage = new PackageStats("com.test.app2"); 106 secondPackage.codeSize = 10; 107 secondPackage.dataSize = 1; 108 secondPackage.cacheSize = 2; 109 mPackages.add(secondPackage); 110 111 DiskStatsFileLogger logger = new DiskStatsFileLogger( 112 mMainResult, mDownloadsResult, mPackages, 0L); 113 logger.dumpToFile(mOutputFile); 114 115 JSONObject output = getOutputFileAsJson(); 116 assertThat(output.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(1111); 117 assertThat(output.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(22); 118 119 JSONArray packageNames = output.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY); 120 assertThat(packageNames.length()).isEqualTo(2); 121 JSONArray appSizes = output.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY); 122 assertThat(appSizes.length()).isEqualTo(2); 123 JSONArray cacheSizes = output.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY); 124 assertThat(cacheSizes.length()).isEqualTo(2); 125 126 // We need to do this crazy Set over this because the DiskStatsFileLogger provides no 127 // guarantee of the ordering of the apps in its output. By using a set, we avoid any order 128 // problems. 129 ArraySet<AppSizeGrouping> apps = new ArraySet<>(); 130 for (int i = 0; i < packageNames.length(); i++) { 131 AppSizeGrouping app = new AppSizeGrouping(packageNames.getString(i), 132 appSizes.getLong(i), cacheSizes.getLong(i)); 133 apps.add(app); 134 } 135 assertThat(apps).containsAllOf(new AppSizeGrouping("com.test.app", 1100, 20), 136 new AppSizeGrouping("com.test.app2", 11, 2)); 137 } 138 139 @Test 140 public void testEmulatedExternalStorageCounted() throws Exception { 141 PackageStats app = new PackageStats("com.test.app"); 142 app.dataSize = 1000; 143 app.externalDataSize = 1000; 144 app.cacheSize = 20; 145 mPackages.add(app); 146 147 DiskStatsFileLogger logger = new DiskStatsFileLogger( 148 mMainResult, mDownloadsResult, mPackages, 0L); 149 logger.dumpToFile(mOutputFile); 150 151 JSONObject output = getOutputFileAsJson(); 152 JSONArray appSizes = output.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY); 153 assertThat(appSizes.length()).isEqualTo(1); 154 assertThat(appSizes.getLong(0)).isEqualTo(2000); 155 } 156 157 @Test 158 public void testDuplicatePackageNameIsNotMergedAcrossMultipleUsers() throws Exception { 159 PackageStats app = new PackageStats("com.test.app"); 160 app.dataSize = 1000; 161 app.externalDataSize = 1000; 162 app.cacheSize = 20; 163 app.userHandle = 0; 164 mPackages.add(app); 165 166 PackageStats secondApp = new PackageStats("com.test.app"); 167 secondApp.dataSize = 100; 168 secondApp.externalDataSize = 100; 169 secondApp.cacheSize = 2; 170 secondApp.userHandle = 1; 171 mPackages.add(secondApp); 172 173 DiskStatsFileLogger logger = new DiskStatsFileLogger( 174 mMainResult, mDownloadsResult, mPackages, 0L); 175 logger.dumpToFile(mOutputFile); 176 177 JSONObject output = getOutputFileAsJson(); 178 assertThat(output.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(2000); 179 assertThat(output.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(20); 180 JSONArray packageNames = output.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY); 181 assertThat(packageNames.length()).isEqualTo(1); 182 assertThat(packageNames.getString(0)).isEqualTo("com.test.app"); 183 184 JSONArray appSizes = output.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY); 185 assertThat(appSizes.length()).isEqualTo(1); 186 assertThat(appSizes.getLong(0)).isEqualTo(2000); 187 188 JSONArray cacheSizes = output.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY); 189 assertThat(cacheSizes.length()).isEqualTo(1); 190 assertThat(cacheSizes.getLong(0)).isEqualTo(20); 191 } 192 193 private JSONObject getOutputFileAsJson() throws Exception { 194 return new JSONObject(IoUtils.readFileAsString(mOutputFile.getAbsolutePath())); 195 } 196 197 /** 198 * This class exists for putting zipped app size information arrays into a set for comparison 199 * purposes. 200 */ 201 private class AppSizeGrouping { 202 public String packageName; 203 public long appSize; 204 public long cacheSize; 205 206 public AppSizeGrouping(String packageName, long appSize, long cacheSize) { 207 this.packageName = packageName; 208 this.appSize = appSize; 209 this.cacheSize = cacheSize; 210 } 211 212 @Override 213 public int hashCode() { 214 int result = 17; 215 result = 37 * result + (int)(appSize ^ (appSize >>> 32)); 216 result = 37 * result + (int)(cacheSize ^ (cacheSize >>> 32)); 217 result = 37 * result + packageName.hashCode(); 218 return result; 219 } 220 221 @Override 222 public boolean equals(Object o) { 223 if (!(o instanceof AppSizeGrouping)) { 224 return false; 225 } 226 if (this == o) { 227 return true; 228 } 229 AppSizeGrouping grouping = (AppSizeGrouping) o; 230 return packageName.equals(grouping.packageName) && appSize == grouping.appSize && 231 cacheSize == grouping.cacheSize; 232 } 233 234 @Override 235 public String toString() { 236 return packageName + " " + appSize + " " + cacheSize; 237 } 238 } 239 }