1 /*
2  * Copyright (C) 2014 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 android.appsecurity.cts;
18 
19 import com.android.ddmlib.testrunner.TestResult.TestStatus;
20 import com.android.tradefed.device.DeviceNotAvailableException;
21 import com.android.tradefed.result.TestDescription;
22 import com.android.tradefed.result.TestResult;
23 import com.android.tradefed.result.TestRunResult;
24 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
25 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
26 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions;
27 
28 import junit.framework.AssertionFailedError;
29 
30 import org.junit.After;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 
35 import java.util.Map;
36 
37 /**
38  * Tests that exercise various storage APIs.
39  */
40 @RunWith(DeviceJUnit4ClassRunner.class)
41 public class StorageHostTest extends BaseHostJUnit4Test {
42     private static final String PKG_STATS = "com.android.cts.storagestatsapp";
43     private static final String PKG_A = "com.android.cts.storageapp_a";
44     private static final String PKG_B = "com.android.cts.storageapp_b";
45     private static final String APK_STATS = "CtsStorageStatsApp.apk";
46     private static final String APK_A = "CtsStorageAppA.apk";
47     private static final String APK_B = "CtsStorageAppB.apk";
48     private static final String CLASS_STATS = "com.android.cts.storagestatsapp.StorageStatsTest";
49     private static final String CLASS = "com.android.cts.storageapp.StorageTest";
50 
51     private int[] mUsers;
52 
53     @Before
setUp()54     public void setUp() throws Exception {
55         mUsers = Utils.prepareMultipleUsers(getDevice());
56 
57         installPackage(APK_STATS);
58         installPackage(APK_A);
59         installPackage(APK_B);
60 
61         for (int user : mUsers) {
62             getDevice().executeShellCommand("appops set --user " + user + " " + PKG_STATS
63                     + " android:get_usage_stats allow");
64         }
65 
66         waitForIdle();
67     }
68 
69     @After
tearDown()70     public void tearDown() throws Exception {
71         getDevice().uninstallPackage(PKG_STATS);
72         getDevice().uninstallPackage(PKG_A);
73         getDevice().uninstallPackage(PKG_B);
74     }
75 
76     @Test
testVerify()77     public void testVerify() throws Exception {
78         Utils.runDeviceTests(getDevice(), PKG_STATS, CLASS_STATS, "testVerify");
79     }
80 
81     @Test
testVerifyAppStats()82     public void testVerifyAppStats() throws Exception {
83         for (int user : mUsers) {
84             runDeviceTests(PKG_A, CLASS, "testAllocate", user);
85         }
86 
87         // for fuse file system
88         Thread.sleep(10000);
89 
90         // TODO: remove this once 34723223 is fixed
91         getDevice().executeShellCommand("sync");
92 
93         for (int user : mUsers) {
94             runDeviceTests(PKG_A, CLASS, "testVerifySpaceManual", user);
95             runDeviceTests(PKG_A, CLASS, "testVerifySpaceApi", user);
96         }
97     }
98 
99     @Test
testVerifyAppQuota()100     public void testVerifyAppQuota() throws Exception {
101         for (int user : mUsers) {
102             runDeviceTests(PKG_A, CLASS, "testVerifyQuotaApi", user);
103         }
104     }
105 
106     @Test
testVerifyAppAllocate()107     public void testVerifyAppAllocate() throws Exception {
108         for (int user : mUsers) {
109             runDeviceTests(PKG_A, CLASS, "testVerifyAllocateApi", user);
110         }
111     }
112 
113     @Test
testVerifySummary()114     public void testVerifySummary() throws Exception {
115         for (int user : mUsers) {
116             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifySummary", user);
117         }
118     }
119 
120     @Test
testVerifyStats()121     public void testVerifyStats() throws Exception {
122         for (int user : mUsers) {
123             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStats", user);
124         }
125     }
126 
127     @Test
testVerifyStatsMultiple()128     public void testVerifyStatsMultiple() throws Exception {
129         for (int user : mUsers) {
130             runDeviceTests(PKG_A, CLASS, "testAllocate", user);
131             runDeviceTests(PKG_A, CLASS, "testAllocate", user);
132 
133             runDeviceTests(PKG_B, CLASS, "testAllocate", user);
134         }
135 
136         for (int user : mUsers) {
137             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsMultiple", user);
138         }
139     }
140 
141     @Test
testVerifyStatsExternal()142     public void testVerifyStatsExternal() throws Exception {
143         for (int user : mUsers) {
144             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternal", user, true);
145         }
146     }
147 
148     @Test
testVerifyStatsExternalConsistent()149     public void testVerifyStatsExternalConsistent() throws Exception {
150         for (int user : mUsers) {
151             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyStatsExternalConsistent", user, true);
152         }
153     }
154 
155     @Test
testVerifyCategory()156     public void testVerifyCategory() throws Exception {
157         for (int user : mUsers) {
158             runDeviceTests(PKG_STATS, CLASS_STATS, "testVerifyCategory", user);
159         }
160     }
161 
162     @Test
testCache()163     public void testCache() throws Exception {
164         // To make the cache clearing logic easier to verify, ignore any cache
165         // and low space reserved space.
166         getDevice().executeShellCommand("settings put global sys_storage_threshold_max_bytes 0");
167         getDevice().executeShellCommand("settings put global sys_storage_cache_max_bytes 0");
168         getDevice().executeShellCommand("svc data disable");
169         getDevice().executeShellCommand("svc wifi disable");
170         try {
171             waitForIdle();
172             for (int user : mUsers) {
173                 // Clear all other cached data to give ourselves a clean slate
174                 getDevice().executeShellCommand("pm trim-caches 4096G");
175                 runDeviceTests(PKG_STATS, CLASS_STATS, "testCacheClearing", user);
176 
177                 getDevice().executeShellCommand("pm trim-caches 4096G");
178                 runDeviceTests(PKG_STATS, CLASS_STATS, "testCacheBehavior", user);
179             }
180         } finally {
181             getDevice().executeShellCommand("settings delete global sys_storage_threshold_max_bytes");
182             getDevice().executeShellCommand("settings delete global sys_storage_cache_max_bytes");
183             getDevice().executeShellCommand("svc data enable");
184             getDevice().executeShellCommand("svc wifi enable");
185         }
186     }
187 
188     @Test
testFullDisk()189     public void testFullDisk() throws Exception {
190         // Clear all other cached and external storage data to give ourselves a
191         // clean slate to test against
192         getDevice().executeShellCommand("pm trim-caches 4096G");
193         getDevice().executeShellCommand("rm -rf /sdcard/*");
194 
195         try {
196             // Try our hardest to fill up the entire disk
197             Utils.runDeviceTestsAsCurrentUser(getDevice(), PKG_B, CLASS, "testFullDisk");
198         } catch (Throwable t) {
199             if (t.getMessage().contains("Skipping")) {
200                 // If the device doens't have resgid support, there's nothing
201                 // for this test to verify
202                 return;
203             } else {
204                 throw new AssertionFailedError(t.getMessage());
205             }
206         }
207 
208         // Tweak something that causes PackageManager to persist data
209         Utils.runDeviceTestsAsCurrentUser(getDevice(), PKG_A, CLASS, "testTweakComponent");
210 
211         // Wake up/unlock device before running tests
212         getDevice().executeShellCommand("input keyevent KEYCODE_WAKEUP");
213         getDevice().disableKeyguard();
214 
215         // Verify that Settings can free space used by abusive app
216         Utils.runDeviceTestsAsCurrentUser(getDevice(), PKG_A, CLASS, "testClearSpace");
217     }
218 
waitForIdle()219     public void waitForIdle() throws Exception {
220         // Try getting all pending events flushed out
221         for (int i = 0; i < 4; i++) {
222             getDevice().executeShellCommand("am wait-for-broadcast-idle");
223             Thread.sleep(500);
224         }
225     }
226 
runDeviceTests(String packageName, String testClassName, String testMethodName, int userId)227     public void runDeviceTests(String packageName, String testClassName, String testMethodName,
228             int userId) throws DeviceNotAvailableException {
229         runDeviceTests(packageName, testClassName, testMethodName, userId, false);
230     }
231 
runDeviceTests(String packageName, String testClassName, String testMethodName, int userId, boolean disableIsolatedStorage)232     public void runDeviceTests(String packageName, String testClassName, String testMethodName,
233             int userId, boolean disableIsolatedStorage) throws DeviceNotAvailableException {
234         final DeviceTestRunOptions options = new DeviceTestRunOptions(packageName);
235         options.setDevice(getDevice());
236         options.setTestClassName(testClassName);
237         options.setTestMethodName(testMethodName);
238         options.setUserId(userId);
239         options.setTestTimeoutMs(20 * 60 * 1000L);
240         options.setDisableIsolatedStorage(disableIsolatedStorage);
241         if (!runDeviceTests(options)) {
242             TestRunResult res = getLastDeviceRunResults();
243             if (res != null) {
244                 StringBuilder errorBuilder = new StringBuilder("on-device tests failed:\n");
245                 for (Map.Entry<TestDescription, TestResult> resultEntry :
246                     res.getTestResults().entrySet()) {
247                     if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
248                         errorBuilder.append(resultEntry.getKey().toString());
249                         errorBuilder.append(":\n");
250                         errorBuilder.append(resultEntry.getValue().getStackTrace());
251                     }
252                 }
253                 throw new AssertionError(errorBuilder.toString());
254             } else {
255                 throw new AssertionFailedError("Error when running device tests.");
256             }
257         }
258     }
259 }
260