blob: 60ede8b7d666193c056026efc37400023c0f9506 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os.storage.cts;
import static android.os.UserHandle.MIN_SECONDARY_USER_ID;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeTrue;
import android.Manifest;
import android.app.UiAutomation;
import android.app.usage.StorageStatsManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.CrateInfo;
import android.os.storage.StorageManager;
import android.text.TextUtils;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.google.common.truth.Correspondence;
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.UUID;
@RunWith(AndroidJUnit4.class)
public class StorageStatsManagerTest {
private static final String CRATES_ROOT = "crates";
private final static boolean ENABLE_STORAGE_CRATES =
SystemProperties.getBoolean("fw.storage_crates", false);
private Context mContext;
private StorageManager mStorageManager;
private StorageStatsManager mStorageStatsManager;
@Rule
public TestName mTestName = new TestName();
private Path mCratesPath;
private Path mCrateDirPath;
private UUID mUuid;
private String mCrateId;
private void cleanAllOfCrates() throws IOException {
if (!mCratesPath.toFile().exists()) {
return;
}
Files.walkFileTree(mCratesPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
Files.deleteIfExists(file);
return super.visitFile(file, attrs);
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
Files.deleteIfExists(dir);
return super.postVisitDirectory(dir, exc);
}
});
Files.deleteIfExists(mCratesPath);
}
/**
* Setup the necessary member field used by test methods.
*/
@Before
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
mStorageStatsManager =
(StorageStatsManager) mContext.getSystemService(Context.STORAGE_STATS_SERVICE);
mCratesPath = mContext.getDataDir().toPath().resolve(CRATES_ROOT);
cleanAllOfCrates();
mCrateId = mTestName.getMethodName();
mCrateDirPath = mCratesPath.resolve(mCrateId);
mUuid = mStorageManager.getUuidForPath(mCratesPath.toFile());
}
/**
* To clean all of crated folders to prevent from flaky.
* @throws Exception happened when the tearDown tries to removed all of folders and files.
*/
@After
public void tearDown() throws Exception {
cleanAllOfCrates();
}
@Test
public void queryCratesForUid_noCratedFolder_shouldBeEmpty() throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
Collection<CrateInfo> collection = mStorageStatsManager.queryCratesForUid(mUuid,
Process.myUid());
assertThat(collection.size()).isEqualTo(0);
}
private Collection<CrateInfo> queryCratesForUser(boolean byShell, UUID uuid,
UserHandle userHandle)
throws PackageManager.NameNotFoundException, IOException {
final UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation()
.getUiAutomation();
if (byShell) {
uiAutomation.adoptShellPermissionIdentity(Manifest.permission.MANAGE_CRATES);
}
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUser(uuid,
userHandle);
if (byShell) {
uiAutomation.dropShellPermissionIdentity();
}
return crateInfos;
}
@Test
public void queryCratesForUser_noCratedFolder_shouldBeEmpty() throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
Collection<CrateInfo> collection = queryCratesForUser(true, mUuid,
Process.myUserHandle());
assertThat(collection.size()).isEqualTo(0);
}
@Test
public void queryCratesForPackage_noCratedFolder_shouldBeEmpty() throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
Collection<CrateInfo> collection = mStorageStatsManager.queryCratesForPackage(mUuid,
mContext.getOpPackageName(), Process.myUserHandle());
assertThat(collection.size()).isEqualTo(0);
}
@Test
public void queryCratesForUid_withOtherUid_shouldRiseSecurityIssueException() throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
int fakeUid = UserHandle.getUid(MIN_SECONDARY_USER_ID,
UserHandle.getAppId(Process.myUid()));
SecurityException securityException = null;
try {
mStorageStatsManager.queryCratesForUid(mUuid, fakeUid);
} catch (SecurityException e) {
securityException = e;
}
assertThat(securityException).isNotNull();
}
@Test
public void queryCratesForUser_withOtherUid_shouldRiseSecurityIssueException()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
UserHandle fakeUserHandle = UserHandle.of(MIN_SECONDARY_USER_ID);
SecurityException securityException = null;
try {
mStorageStatsManager.queryCratesForUser(mUuid, fakeUserHandle);
} catch (SecurityException e) {
securityException = e;
}
assertThat(securityException).isNotNull();
}
@Test
public void queryCratesForPackage_withOtherUid_shouldRiseSecurityIssueException()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
UserHandle fakeUserHandle = UserHandle.of(MIN_SECONDARY_USER_ID);
SecurityException securityException = null;
try {
mStorageStatsManager.queryCratesForPackage(mUuid,
mContext.getOpPackageName(), fakeUserHandle);
} catch (SecurityException e) {
securityException = e;
}
assertThat(securityException).isNotNull();
}
@Test
public void queryCratesForUid_addOneDirectory_shouldIncreasingOneCrate()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
Collection<CrateInfo> originalCollection = mStorageStatsManager.queryCratesForUid(
mUuid, Process.myUid());
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForUid(
mUuid, Process.myUid());
assertThat(newCollection.size()).isEqualTo(originalCollection.size() + 1);
}
@Test
public void queryCratesForUser_addOneDirectory_shouldIncreasingOneCrate()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
Collection<CrateInfo> originalCollection = queryCratesForUser(true, mUuid,
Process.myUserHandle());
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> newCollection = queryCratesForUser(true,
mUuid, Process.myUserHandle());
assertThat(newCollection.size()).isEqualTo(originalCollection.size() + 1);
}
@Test
public void queryCratesForPackage_addOneDirectory_shouldIncreasingOneCrate()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
Collection<CrateInfo> originalCollection = mStorageStatsManager.queryCratesForPackage(
mUuid, mContext.getOpPackageName(), Process.myUserHandle());
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForPackage(
mUuid, mContext.getOpPackageName(), Process.myUserHandle());
assertThat(newCollection.size()).isEqualTo(originalCollection.size() + 1);
}
@Test
public void queryCratesForUid_withoutSetCrateInfo_labelShouldTheSameWithFolderName()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUid(
mUuid, Process.myUid());
assertThat(crateInfos.iterator().next().getLabel()).isEqualTo(mTestName.getMethodName());
}
@Test
public void queryCratesForUser_withoutSetCrateInfo_labelShouldTheSameWithFolderName()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> crateInfos = queryCratesForUser(true, mUuid,
Process.myUserHandle());
assertThat(crateInfos.iterator().next().getLabel()).isEqualTo(mTestName.getMethodName());
}
@Test
public void queryCratesForPackage_withoutSetCrateInfo_labelShouldTheSameWithFolderName()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForPackage(
mUuid, mContext.getOpPackageName(), Process.myUserHandle());
assertThat(crateInfos.iterator().next().getLabel()).isEqualTo(mTestName.getMethodName());
}
@Test
public void queryCratesForUid_withoutSetCrateInfo_expirationShouldBeZero()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUid(
mUuid, Process.myUid());
assertThat(crateInfos.iterator().next().getExpirationMillis()).isEqualTo(0);
}
@Test
public void queryCratesForUser_withoutSetCrateInfo_expirationShouldBeZero()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> crateInfos = queryCratesForUser(true, mUuid,
Process.myUserHandle());
assertThat(crateInfos.iterator().next().getExpirationMillis()).isEqualTo(0);
}
@Test
public void queryCratesForPackage_withoutSetCrateInfo_expirationShouldBeZero()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
mContext.getCrateDir(mCrateId);
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForPackage(
mUuid, mContext.getOpPackageName(), Process.myUserHandle());
assertThat(crateInfos.iterator().next().getExpirationMillis()).isEqualTo(0);
}
@Test
public void queryCratesForUid_removeCratedDir_shouldDecreaseTheNumberOfCrates()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
for (int i = 0; i < 3; i++) {
mContext.getCrateDir(mCrateId + "_" + i);
}
Collection<CrateInfo> oldCollection = mStorageStatsManager.queryCratesForUid(mUuid,
Process.myUid());
Files.deleteIfExists(mContext.getCrateDir(mCrateId + "_" + 1).toPath());
Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForUid(
mUuid, Process.myUid());
assertThat(newCollection.size()).isEqualTo(oldCollection.size() - 1);
}
@Test
public void queryCratesForPackage_removeCratedDir_shouldDecreaseTheNumberOfCrates()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
for (int i = 0; i < 3; i++) {
mContext.getCrateDir(mCrateId + "_" + i);
}
Collection<CrateInfo> oldCollection = mStorageStatsManager.queryCratesForPackage(mUuid,
mContext.getOpPackageName(), Process.myUserHandle());
Files.deleteIfExists(mContext.getCrateDir(mCrateId + "_" + 1).toPath());
Collection<CrateInfo> newCollection = mStorageStatsManager.queryCratesForPackage(mUuid,
mContext.getOpPackageName(), Process.myUserHandle());
assertThat(newCollection.size()).isEqualTo(oldCollection.size() - 1);
}
@Test
public void queryCratesForUser_removeCratedDir_shouldDecreaseTheNumberOfCrates()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
for (int i = 0; i < 3; i++) {
mContext.getCrateDir(mCrateId + "_" + i);
}
Collection<CrateInfo> oldCollection = queryCratesForUser(true, mUuid,
Process.myUserHandle());
Files.deleteIfExists(mContext.getCrateDir(mCrateId + "_" + 1).toPath());
Collection<CrateInfo> newCollection = queryCratesForUser(true, mUuid,
Process.myUserHandle());
assertThat(newCollection.size()).isEqualTo(oldCollection.size() - 1);
}
Correspondence<CrateInfo, String> mCorrespondenceByLabel = new Correspondence<>() {
@Override
public boolean compare(CrateInfo crateInfo, String expect) {
return TextUtils.equals(crateInfo.getLabel(), expect);
}
@Override
public String toString() {
return "It should be the crated folder name";
}
};
@Test
public void queryCratesForUid_createDeepPath_shouldCreateOneCrate()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
final Path threeLevelPath = mCrateDirPath.resolve("1").resolve("2").resolve("3");
Files.createDirectories(threeLevelPath);
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForUid(
mUuid, Process.myUid());
assertThat(crateInfos).comparingElementsUsing(mCorrespondenceByLabel)
.containsExactly(mCrateId);
}
@Test
public void queryCratesForUser_createDeepPath_shouldCreateOneCrate()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
final Path threeLevelPath = mCrateDirPath.resolve("1").resolve("2").resolve("3");
Files.createDirectories(threeLevelPath);
Collection<CrateInfo> crateInfos = queryCratesForUser(true, mUuid,
Process.myUserHandle());
assertThat(crateInfos).comparingElementsUsing(mCorrespondenceByLabel)
.containsExactly(mCrateId);
}
@Test
public void queryCratesForPackage_createDeepPath_shouldCreateOneCrate()
throws Exception {
assumeTrue("only test on the device with storage crates feature", ENABLE_STORAGE_CRATES);
final Path threeLevelPath = mCrateDirPath.resolve("1").resolve("2").resolve("3");
Files.createDirectories(threeLevelPath);
Collection<CrateInfo> crateInfos = mStorageStatsManager.queryCratesForPackage(
mUuid, mContext.getOpPackageName(), Process.myUserHandle());
assertThat(crateInfos).comparingElementsUsing(mCorrespondenceByLabel)
.containsExactly(mCrateId);
}
}