1 /* 2 * Copyright (C) 2017 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.storageapp; 18 19 import android.content.Context; 20 import android.system.Os; 21 import android.system.OsConstants; 22 import android.system.StructUtsname; 23 import android.util.Log; 24 25 import junit.framework.AssertionFailedError; 26 27 import java.io.BufferedReader; 28 import java.io.ByteArrayOutputStream; 29 import java.io.File; 30 import java.io.FileDescriptor; 31 import java.io.FileOutputStream; 32 import java.io.FileReader; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import java.io.OutputStream; 36 import java.util.Arrays; 37 import java.util.regex.Matcher; 38 import java.util.regex.Pattern; 39 40 public class Utils { 41 public static final String TAG = "StorageApp"; 42 43 public static final String PKG_A = "com.android.cts.storageapp_a"; 44 public static final String PKG_B = "com.android.cts.storageapp_b"; 45 public static final String PKG_C = "com.android.cts.storageapp_c"; 46 47 public static final String REF_PROFILES_BASE_DIR = "/data/misc/profiles/ref/"; 48 public static final String CUR_PROFILES_BASE_DIR = "/data/misc/profiles/cur/"; 49 public static final String PROFILE_FILE_NAME = "primary.prof"; 50 51 // You will pry my kibibytes from my cold dead hands! But to make test 52 // results easier to debug, we'll use kilobytes... 53 public static final long KB_IN_BYTES = 1000; 54 public static final long MB_IN_BYTES = KB_IN_BYTES * 1000; 55 public static final long GB_IN_BYTES = MB_IN_BYTES * 1000; 56 57 public static final long DATA_INT = (2 + 3 + 5 + 13 + 17 + 19 + 23) * MB_IN_BYTES; 58 public static final long DATA_EXT = (7 + 11) * MB_IN_BYTES; 59 public static final long DATA_ALL = DATA_INT + DATA_EXT; // 100MB 60 61 public static final long CACHE_INT = (3 + 5 + 17 + 19 + 23) * MB_IN_BYTES; 62 public static final long CACHE_EXT = (11) * MB_IN_BYTES; 63 public static final long CACHE_ALL = CACHE_INT + CACHE_EXT; // 78MB 64 65 public static final long CODE_ALL = 29 * MB_IN_BYTES; 66 useSpace(Context c)67 public static void useSpace(Context c) throws Exception { 68 // We use prime numbers for all values so that we can easily identify 69 // which file(s) are missing from broken test results. 70 useWrite(makeUniqueFile(c.getFilesDir()), 2 * MB_IN_BYTES); 71 useWrite(makeUniqueFile(c.getCodeCacheDir()), 3 * MB_IN_BYTES); 72 useWrite(makeUniqueFile(c.getCacheDir()), 5 * MB_IN_BYTES); 73 useWrite(makeUniqueFile(c.getExternalFilesDir("meow")), 7 * MB_IN_BYTES); 74 useWrite(makeUniqueFile(c.getExternalCacheDir()), 11 * MB_IN_BYTES); 75 76 useFallocate(makeUniqueFile(c.getFilesDir()), 13 * MB_IN_BYTES); 77 useFallocate(makeUniqueFile(c.getCodeCacheDir()), 17 * MB_IN_BYTES); 78 useFallocate(makeUniqueFile(c.getCacheDir()), 19 * MB_IN_BYTES); 79 final File subdir = makeUniqueFile(c.getCacheDir()); 80 Os.mkdir(subdir.getAbsolutePath(), 0700); 81 useFallocate(makeUniqueFile(subdir), 23 * MB_IN_BYTES); 82 83 useWrite(makeUniqueFile(c.getObbDir()), 29 * MB_IN_BYTES); 84 } 85 assertAtLeast(long expected, long actual)86 public static void assertAtLeast(long expected, long actual) { 87 if (actual < expected) { 88 throw new AssertionFailedError("Expected at least " + expected + " but was " + actual 89 + " [" + android.os.Process.myUserHandle() + "]"); 90 } 91 } 92 assertMostlyEquals(long expected, long actual)93 public static void assertMostlyEquals(long expected, long actual) { 94 assertMostlyEquals(expected, actual, 500 * KB_IN_BYTES); 95 } 96 assertMostlyEquals(long expected, long actual, long delta)97 public static void assertMostlyEquals(long expected, long actual, long delta) { 98 if (Math.abs(expected - actual) > delta) { 99 throw new AssertionFailedError("Expected roughly " + expected + " but was " + actual 100 + " [" + android.os.Process.myUserHandle() + "]"); 101 } 102 } 103 makeUniqueFile(File dir)104 public static File makeUniqueFile(File dir) { 105 return new File(dir, Long.toString(System.nanoTime())); 106 } 107 useWrite(File file, long size)108 public static File useWrite(File file, long size) throws Exception { 109 try (FileOutputStream os = new FileOutputStream(file)) { 110 final byte[] buf = new byte[1024]; 111 while (size > 0) { 112 os.write(buf, 0, (int) Math.min(buf.length, size)); 113 size -= buf.length; 114 } 115 } 116 return file; 117 } 118 useFallocate(File file, long length, long time)119 public static File useFallocate(File file, long length, long time) throws Exception { 120 final File res = useFallocate(file, length); 121 file.setLastModified(time); 122 return res; 123 } 124 useFallocate(File file, long length)125 public static File useFallocate(File file, long length) throws Exception { 126 final FileDescriptor fd = Os.open(file.getAbsolutePath(), 127 OsConstants.O_CREAT | OsConstants.O_RDWR | OsConstants.O_TRUNC, 0700); 128 try { 129 Os.posix_fallocate(fd, 0, length); 130 } finally { 131 Os.close(fd); 132 } 133 return file; 134 } 135 getSizeManual(File dir)136 public static long getSizeManual(File dir) throws Exception { 137 return getSizeManual(dir, false); 138 } 139 getSizeManual(File dir, boolean excludeObb)140 public static long getSizeManual(File dir, boolean excludeObb) throws Exception { 141 long size = getAllocatedSize(dir); 142 File[] files = dir.listFiles(); 143 144 if (files == null) { 145 // This can happen on devices with scoped storage, where we're not allowed 146 // to iterate Android/ anymore. 147 return size; 148 } 149 150 for (File f : files) { 151 if (f.isDirectory()) { 152 if (excludeObb && f.getName().equalsIgnoreCase("obb") 153 && f.getParentFile().getName().equalsIgnoreCase("Android")) { 154 Log.d(TAG, "Ignoring OBB directory " + f); 155 } else { 156 size += getSizeManual(f, excludeObb); 157 } 158 } else { 159 size += getAllocatedSize(f); 160 } 161 } 162 return size; 163 } 164 getAllocatedSize(File f)165 private static long getAllocatedSize(File f) throws Exception { 166 return Os.lstat(f.getAbsolutePath()).st_blocks * 512 / 167 Os.lstat(f.getAbsolutePath()).st_blksize * 168 Os.lstat(f.getAbsolutePath()).st_blksize ; 169 } 170 deleteContents(File dir)171 public static boolean deleteContents(File dir) { 172 File[] files = dir.listFiles(); 173 boolean success = true; 174 if (files != null) { 175 for (File file : files) { 176 if (file.isDirectory()) { 177 success &= deleteContents(file); 178 } 179 if (!file.delete()) { 180 success = false; 181 } 182 } 183 } 184 return success; 185 } 186 logCommand(String... cmd)187 public static void logCommand(String... cmd) throws Exception { 188 final Process proc = new ProcessBuilder(cmd).redirectErrorStream(true).start(); 189 190 final ByteArrayOutputStream buf = new ByteArrayOutputStream(); 191 copy(proc.getInputStream(), buf); 192 final int res = proc.waitFor(); 193 194 Log.d(TAG, Arrays.toString(cmd) + " result " + res + ":"); 195 Log.d(TAG, buf.toString()); 196 } 197 198 /** Shamelessly lifted from libcore.io.Streams */ copy(InputStream in, OutputStream out)199 public static int copy(InputStream in, OutputStream out) throws IOException { 200 int total = 0; 201 byte[] buffer = new byte[8192]; 202 int c; 203 while ((c = in.read(buffer)) != -1) { 204 total += c; 205 out.write(buffer, 0, c); 206 } 207 return total; 208 } 209 } 210