1 /* 2 * Copyright (C) 2010 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.dumprendertree2; 18 19 import android.util.Log; 20 21 import com.android.dumprendertree2.forwarder.ForwarderManager; 22 23 import java.io.BufferedReader; 24 import java.io.File; 25 import java.io.FileNotFoundException; 26 import java.io.IOException; 27 import java.io.InputStream; 28 import java.io.InputStreamReader; 29 import java.io.StringReader; 30 import java.net.MalformedURLException; 31 import java.net.URL; 32 import java.net.URLConnection; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.HashSet; 36 import java.util.List; 37 import java.util.Set; 38 39 /** 40 * A utility to filter out some files/directories from the views and tests that run. 41 */ 42 public class FileFilter { 43 private static final String LOG_TAG = "FileFilter"; 44 45 private static final String TEST_EXPECTATIONS_TXT_PATH = 46 "platform/android/test_expectations.txt"; 47 48 private static final String HTTP_TESTS_PATH = "http/tests/"; 49 private static final String SSL_PATH = "ssl/"; 50 51 private static final String TOKEN_CRASH = "CRASH"; 52 private static final String TOKEN_FAIL = "FAIL"; 53 private static final String TOKEN_SLOW = "SLOW"; 54 55 private final Set<String> mCrashList = new HashSet<String>(); 56 private final Set<String> mFailList = new HashSet<String>(); 57 private final Set<String> mSlowList = new HashSet<String>(); 58 59 public FileFilter() { 60 loadTestExpectations(); 61 } 62 63 private static final String trimTrailingSlashIfPresent(String path) { 64 File file = new File(path); 65 return file.getPath(); 66 } 67 68 public void loadTestExpectations() { 69 URL url = null; 70 try { 71 url = new URL(ForwarderManager.getHostSchemePort(false) + 72 "LayoutTests/" + TEST_EXPECTATIONS_TXT_PATH); 73 } catch (MalformedURLException e) { 74 assert false; 75 } 76 77 try { 78 InputStream inputStream = null; 79 BufferedReader bufferedReader = null; 80 try { 81 byte[] httpAnswer = FsUtils.readDataFromUrl(url); 82 if (httpAnswer == null) { 83 Log.w(LOG_TAG, "loadTestExpectations(): File not found: " + 84 TEST_EXPECTATIONS_TXT_PATH); 85 return; 86 } 87 bufferedReader = new BufferedReader(new StringReader( 88 new String(httpAnswer))); 89 String line; 90 String entry; 91 String[] parts; 92 String path; 93 Set<String> tokens; 94 while (true) { 95 line = bufferedReader.readLine(); 96 if (line == null) { 97 break; 98 } 99 100 /** Remove the comment and trim */ 101 entry = line.split("//", 2)[0].trim(); 102 103 /** Omit empty lines, advance to next line */ 104 if (entry.isEmpty()) { 105 continue; 106 } 107 108 /** Split on whitespace into path part and the rest */ 109 parts = entry.split("\\s", 2); 110 111 /** At this point parts.length >= 1 */ 112 if (parts.length == 1) { 113 Log.w(LOG_TAG + "::reloadConfiguration", 114 "There are no options specified for the test!"); 115 continue; 116 } 117 118 path = trimTrailingSlashIfPresent(parts[0]); 119 120 /** Split on whitespace */ 121 tokens = new HashSet<String>(Arrays.asList( 122 parts[1].split("\\s", 0))); 123 124 /** Chose the right collections to add to */ 125 if (tokens.contains(TOKEN_CRASH)) { 126 mCrashList.add(path); 127 128 /** If test is on skip list we ignore any further options */ 129 continue; 130 } 131 132 if (tokens.contains(TOKEN_FAIL)) { 133 mFailList.add(path); 134 } 135 if (tokens.contains(TOKEN_SLOW)) { 136 mSlowList.add(path); 137 } 138 } 139 } finally { 140 if (inputStream != null) { 141 inputStream.close(); 142 } 143 if (bufferedReader != null) { 144 bufferedReader.close(); 145 } 146 } 147 } catch (IOException e) { 148 Log.e(LOG_TAG, "url=" + url, e); 149 } 150 } 151 152 /** 153 * Checks if test is expected to crash. 154 * 155 * <p> 156 * Path given should relative within LayoutTests folder, e.g. fast/dom/foo.html 157 * 158 * @param testPath 159 * - a relative path within LayoutTests folder 160 * @return if the test is supposed to be skipped 161 */ 162 public boolean isCrash(String testPath) { 163 for (String prefix : getPrefixes(testPath)) { 164 if (mCrashList.contains(prefix)) { 165 return true; 166 } 167 } 168 169 return false; 170 } 171 172 /** 173 * Checks if test result is supposed to be "failed". 174 * 175 * <p> 176 * Path given should relative within LayoutTests folder, e.g. fast/dom/foo.html 177 * 178 * @param testPath 179 * - a relative path within LayoutTests folder 180 * @return if the test result is supposed to be "failed" 181 */ 182 public boolean isFail(String testPath) { 183 for (String prefix : getPrefixes(testPath)) { 184 if (mFailList.contains(prefix)) { 185 return true; 186 } 187 } 188 189 return false; 190 } 191 192 /** 193 * Checks if test is slow and should have timeout increased. 194 * 195 * <p> 196 * Path given should relative within LayoutTests folder, e.g. fast/dom/foo.html 197 * 198 * @param testPath 199 * - a relative path within LayoutTests folder 200 * @return if the test is slow and should have timeout increased. 201 */ 202 public boolean isSlow(String testPath) { 203 for (String prefix : getPrefixes(testPath)) { 204 if (mSlowList.contains(prefix)) { 205 return true; 206 } 207 } 208 209 return false; 210 } 211 212 /** 213 * Returns the list of all path prefixes of the given path. 214 * 215 * <p> 216 * e.g. this/is/a/path returns the list: this this/is this/is/a this/is/a/path 217 * 218 * @param path 219 * @return the list of all path prefixes of the given path. 220 */ 221 private static List<String> getPrefixes(String path) { 222 File file = new File(path); 223 List<String> prefixes = new ArrayList<String>(8); 224 225 do { 226 prefixes.add(file.getPath()); 227 file = file.getParentFile(); 228 } while (file != null); 229 230 return prefixes; 231 } 232 233 /** 234 * Checks if the directory may contain tests or contains just helper files. 235 * 236 * @param dirName 237 * @return 238 * if the directory may contain tests 239 */ 240 public static boolean isTestDir(String dirName) { 241 return (!dirName.equals("script-tests") 242 && !dirName.equals("resources") && !dirName.startsWith(".")); 243 } 244 245 /** 246 * Checks if the file is a test. 247 * Currently we run .html, .xhtml and .php tests. 248 * 249 * @warning You MUST also call isTestDir() on the parent directory before 250 * assuming that a file is a test. 251 * 252 * @param testName 253 * @return if the file is a test 254 */ 255 public static boolean isTestFile(String testName) { 256 return testName.endsWith(".html") 257 || testName.endsWith(".xhtml") 258 || testName.endsWith(".php"); 259 } 260 261 /** 262 * Return a URL of the test on the server. 263 * 264 * @param relativePath 265 * @param allowHttps Whether to allow the use of HTTPS, even if the file is in the SSL 266 * directory. 267 * @return a URL of the test on the server 268 */ 269 public static URL getUrl(String relativePath, boolean allowHttps) { 270 String urlBase = ForwarderManager.getHostSchemePort(false); 271 272 /** 273 * URL is formed differently for HTTP vs non-HTTP tests, because HTTP tests 274 * expect different document root. See run_apache2.py and .conf file for details 275 */ 276 if (relativePath.startsWith(HTTP_TESTS_PATH)) { 277 relativePath = relativePath.substring(HTTP_TESTS_PATH.length()); 278 if (relativePath.startsWith(SSL_PATH) && allowHttps) { 279 urlBase = ForwarderManager.getHostSchemePort(true); 280 } 281 } else { 282 relativePath = "LayoutTests/" + relativePath; 283 } 284 285 try { 286 return new URL(urlBase + relativePath); 287 } catch (MalformedURLException e) { 288 Log.e(LOG_TAG, "Malformed URL!", e); 289 } 290 291 return null; 292 } 293 294 /** 295 * If the path contains extension (e.g .foo at the end of the file) then it changes 296 * this (.foo) into newEnding (so it has to contain the dot if we want to preserve it). 297 * 298 * <p>If the path doesn't contain an extension, it adds the ending to the path. 299 * 300 * @param relativePath 301 * @param newEnding 302 * @return 303 * a new path, containing the newExtension 304 */ 305 public static String setPathEnding(String relativePath, String newEnding) { 306 int dotPos = relativePath.lastIndexOf('.'); 307 if (dotPos == -1) { 308 return relativePath + newEnding; 309 } 310 311 return relativePath.substring(0, dotPos) + newEnding; 312 } 313 } 314