1 /* 2 * Copyright (C) 2020 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.cts.appdataisolation.common; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertTrue; 22 import static org.testng.Assert.assertEquals; 23 import static org.testng.Assert.fail; 24 import static org.testng.Assert.expectThrows; 25 26 import android.system.ErrnoException; 27 import android.system.Os; 28 import android.system.OsConstants; 29 30 import java.io.File; 31 import java.io.FileInputStream; 32 import java.io.FileNotFoundException; 33 import java.io.IOException; 34 35 /* 36 * This class is a helper class for test app file operations. 37 */ 38 public class FileUtils { 39 40 public static final String APPA_PKG = "com.android.cts.appdataisolation.appa"; 41 public static final String APPB_PKG = "com.android.cts.appdataisolation.appb"; 42 public static final String NOT_INSTALLED_PKG = "com.android.cts.appdataisolation.not_installed_pkg"; 43 44 public static final String CE_DATA_FILE_NAME = "ce_data_file"; 45 public static final String DE_DATA_FILE_NAME = "de_data_file"; 46 public final static String EXTERNAL_DATA_FILE_NAME = "external_data_file"; 47 public final static String OBB_FILE_NAME = "obb_file"; 48 49 private static final String JAVA_FILE_PERMISSION_DENIED_MSG = 50 "open failed: EACCES (Permission denied)"; 51 private static final String JAVA_FILE_NOT_FOUND_MSG = 52 "open failed: ENOENT (No such file or directory)"; 53 assertDirIsNotAccessible(String path)54 public static void assertDirIsNotAccessible(String path) { 55 // Trying to access a file that does not exist in that directory, it should return 56 // permission denied not file not found. 57 Exception exception = expectThrows(FileNotFoundException.class, () -> { 58 new FileInputStream(new File(path, "FILE_DOES_NOT_EXIST")); 59 }); 60 assertThat(exception.getMessage()).contains(JAVA_FILE_PERMISSION_DENIED_MSG); 61 assertThat(exception.getMessage()).doesNotContain(JAVA_FILE_NOT_FOUND_MSG); 62 63 assertThat(new File(path).canExecute()).isFalse(); 64 } 65 assertDirDoesNotExist(String path)66 public static void assertDirDoesNotExist(String path) { 67 File directory = new File(path); 68 // Trying to access a file/directory that does exist, but is not visible to the caller, it 69 // should return file not found. 70 Exception exception = expectThrows(FileNotFoundException.class, () -> { 71 new FileInputStream(directory); 72 }); 73 assertThat(exception.getMessage()).contains(JAVA_FILE_NOT_FOUND_MSG); 74 assertThat(exception.getMessage()).doesNotContain(JAVA_FILE_PERMISSION_DENIED_MSG); 75 76 File parent = directory.getParentFile(); 77 if (parent != null && !parent.exists()) { 78 // If the parent directory doesn't exist then we can be confident this 79 // directory is entirely invisible. 80 return; 81 } 82 // Try to create a directory here, and it should return permission denied not directory 83 // exists. 84 try { 85 Os.mkdir(path, 0700); 86 fail("Should not able to mkdir() on " + path); 87 } catch (ErrnoException e) { 88 assertEquals(e.errno, OsConstants.EACCES, "Error on path: " + path); 89 } 90 91 assertThat(directory.exists()).isFalse(); 92 } 93 assertDirIsAccessible(String path)94 public static void assertDirIsAccessible(String path) { 95 // This can ensure directory path exists, and by trying to access a file doesn't exist, 96 // if app has search permission to that directory, it should return file not found 97 // and not security exception. 98 assertFileDoesNotExist(path, "FILE_DOES_NOT_EXIST"); 99 100 assertThat(new File(path).canExecute()).isTrue(); 101 } 102 assertFileIsAccessible(String path)103 public static void assertFileIsAccessible(String path) { 104 try (FileInputStream is = new FileInputStream(path)) { 105 is.read(); 106 } catch (IOException e) { 107 fail("Could not read file: " + path, e); 108 } 109 } 110 assertFileDoesNotExist(String path, String name)111 public static void assertFileDoesNotExist(String path, String name) { 112 // Make sure parent dir exists 113 File directory = new File(path); 114 assertTrue(directory.exists()); 115 116 Exception exception = expectThrows(FileNotFoundException.class, () -> { 117 new FileInputStream(new File(path, name)); 118 }); 119 assertThat(exception.getMessage()).contains(JAVA_FILE_NOT_FOUND_MSG); 120 assertThat(exception.getMessage()).doesNotContain(JAVA_FILE_PERMISSION_DENIED_MSG); 121 } 122 assertFileExists(String path, String name)123 public static void assertFileExists(String path, String name) { 124 File file = new File(path, name); 125 assertTrue(file.exists()); 126 } 127 touchFile(String path, String name)128 public static void touchFile(String path, String name) throws IOException { 129 File file = new File(path, name); 130 file.createNewFile(); 131 } 132 deleteFile(String path, String name)133 public static void deleteFile(String path, String name) throws IOException { 134 File file = new File(path, name); 135 file.delete(); 136 } 137 replacePackageAWithPackageB(String path)138 public static String replacePackageAWithPackageB(String path) { 139 return path.replace(APPA_PKG, APPB_PKG); 140 } 141 replacePackageAWithNotInstalledPkg(String path)142 public static String replacePackageAWithNotInstalledPkg(String path) { 143 return path.replace(APPA_PKG, NOT_INSTALLED_PKG); 144 } 145 } 146