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