[Android WebViewShell] Add inclusion test for webview exposed stable interfaces.
[chromium-blink-merge.git] / android_webview / tools / WebViewShell / src / org / chromium / webview_shell / WebViewLayoutTest.java
blob4d6414adf21d92c41e9177909dbe3e55a43ad088
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.webview_shell;
7 import android.os.Environment;
8 import android.test.ActivityInstrumentationTestCase2;
10 import org.chromium.base.Log;
12 import java.io.BufferedReader;
13 import java.io.File;
14 import java.io.FileInputStream;
15 import java.io.FileNotFoundException;
16 import java.io.FileOutputStream;
17 import java.io.IOException;
18 import java.io.InputStreamReader;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.concurrent.TimeUnit;
22 import java.util.concurrent.TimeoutException;
24 /**
25 * Tests running end-to-end layout tests.
27 public class WebViewLayoutTest
28 extends ActivityInstrumentationTestCase2<WebViewLayoutTestActivity> {
30 private static final String TAG = "WebViewLayoutTest";
32 private static final String EXTERNAL_PREFIX =
33 Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
34 private static final String BASE_WEBVIEW_TEST_PATH = "android_webview/tools/WebViewShell/test/";
35 private static final String BASE_BLINK_TEST_PATH = "third_party/WebKit/LayoutTests/";
36 private static final String BASE_BLINK_STABLE_TEST_PATH =
37 BASE_BLINK_TEST_PATH + "virtual/stable/";
38 private static final String PATH_WEBVIEW_PREFIX = EXTERNAL_PREFIX + BASE_WEBVIEW_TEST_PATH;
39 private static final String PATH_BLINK_PREFIX = EXTERNAL_PREFIX + BASE_BLINK_TEST_PATH;
40 private static final String PATH_BLINK_STABLE_PREFIX =
41 EXTERNAL_PREFIX + BASE_BLINK_STABLE_TEST_PATH;
43 private static final long TIMEOUT_SECONDS = 20;
45 private WebViewLayoutTestActivity mTestActivity;
47 public WebViewLayoutTest() {
48 super(WebViewLayoutTestActivity.class);
51 @Override
52 protected void setUp() throws Exception {
53 super.setUp();
54 mTestActivity = (WebViewLayoutTestActivity) getActivity();
57 @Override
58 protected void tearDown() throws Exception {
59 mTestActivity.finish();
60 super.tearDown();
63 @Override
64 public WebViewLayoutTestRunner getInstrumentation() {
65 return (WebViewLayoutTestRunner) super.getInstrumentation();
68 public void testSimple() throws Exception {
69 runWebViewLayoutTest("experimental/basic-logging.html",
70 "experimental/basic-logging-expected.txt");
73 public void testGlobalInterface() throws Exception {
74 runBlinkLayoutTest("webexposed/global-interface-listing.html",
75 "webexposed/global-interface-listing-expected.txt");
78 public void testWebViewExcludedInterfaces() throws Exception {
79 ensureJsTestCopied();
80 loadUrlWebViewAsync("file://" + PATH_BLINK_PREFIX
81 + "webexposed/global-interface-listing.html", mTestActivity);
82 String blinkExpected = readFile(PATH_BLINK_PREFIX
83 + "webexposed/global-interface-listing-expected.txt");
84 String webviewExcluded = readFile(PATH_WEBVIEW_PREFIX
85 + "webexposed/not-webview-exposed.txt");
86 mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
87 String result = mTestActivity.getTestResult();
89 HashMap<String, HashSet<String>> webviewExcludedInterfacesMap =
90 buildHashMap(webviewExcluded);
91 HashMap<String, HashSet<String>> webviewInterfacesMap = buildHashMap(result);
92 HashMap<String, HashSet<String>> blinkInterfacesMap = buildHashMap(blinkExpected);
93 StringBuilder unexpected = new StringBuilder();
95 // Check that each excluded interface is present in blinkInterfacesMap but not
96 // in webviewInterfacesMap.
97 for (String interfaceS : webviewExcludedInterfacesMap.keySet()) {
98 assertNotNull("Interface " + interfaceS + " not exposed in blink",
99 blinkInterfacesMap.get(interfaceS));
100 if (webviewInterfacesMap.get(interfaceS) != null) {
101 unexpected.append(interfaceS + "\n");
104 assertEquals("Unexpected webview interfaces found", "", unexpected.toString());
107 public void testWebViewIncludedStableInterfaces() throws Exception {
108 ensureJsTestCopied();
109 loadUrlWebViewAsync("file://" + PATH_BLINK_PREFIX
110 + "webexposed/global-interface-listing.html", mTestActivity);
111 String blinkStableExpected = readFile(PATH_BLINK_STABLE_PREFIX
112 + "webexposed/global-interface-listing-expected.txt");
113 String webviewExcluded = readFile(PATH_WEBVIEW_PREFIX
114 + "webexposed/not-webview-exposed.txt");
115 mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
116 String result = mTestActivity.getTestResult();
118 HashMap<String, HashSet<String>> webviewExcludedInterfacesMap =
119 buildHashMap(webviewExcluded);
120 HashMap<String, HashSet<String>> webviewInterfacesMap = buildHashMap(result);
121 HashMap<String, HashSet<String>> blinkStableInterfacesMap =
122 buildHashMap(blinkStableExpected);
123 StringBuilder missing = new StringBuilder();
125 // Check that each stable blink interface is present in webview except the excluded
126 // interfaces.
127 for (String interfaceS : blinkStableInterfacesMap.keySet()) {
128 // TODO(timvolodine): consider implementing matching of subsets as well.
129 HashSet<String> subsetExcluded = webviewExcludedInterfacesMap.get(interfaceS);
130 if (subsetExcluded != null && subsetExcluded.isEmpty()) continue;
132 if (webviewInterfacesMap.get(interfaceS) == null) {
133 missing.append(interfaceS + "\n");
136 assertEquals("Missing webview interfaces found", "", missing.toString());
139 // test helper methods
141 private void runWebViewLayoutTest(final String fileName, final String fileNameExpected)
142 throws Exception {
143 runTest(PATH_WEBVIEW_PREFIX + fileName, PATH_WEBVIEW_PREFIX + fileNameExpected);
146 private void runBlinkLayoutTest(final String fileName, final String fileNameExpected)
147 throws Exception {
148 ensureJsTestCopied();
149 runTest(PATH_BLINK_PREFIX + fileName, PATH_WEBVIEW_PREFIX + fileNameExpected);
152 private void runTest(final String fileName, final String fileNameExpected)
153 throws FileNotFoundException, IOException, InterruptedException, TimeoutException {
154 loadUrlWebViewAsync("file://" + fileName, mTestActivity);
156 if (getInstrumentation().isRebaseline()) {
157 // this is the rebaseline process
158 mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
159 String result = mTestActivity.getTestResult();
160 writeFile(fileNameExpected, result, true);
161 Log.i(TAG, "file: " + fileNameExpected + " --> rebaselined, length=" + result.length());
162 } else {
163 String expected = readFile(fileNameExpected);
164 mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
165 String result = mTestActivity.getTestResult();
166 assertEquals(expected, result);
170 private void loadUrlWebViewAsync(final String fileUrl,
171 final WebViewLayoutTestActivity activity) {
172 getInstrumentation().runOnMainSync(new Runnable() {
173 @Override
174 public void run() {
175 activity.loadUrl(fileUrl);
180 private static void ensureJsTestCopied() throws IOException {
181 File jsTestFile = new File(PATH_BLINK_PREFIX + "resources/js-test.js");
182 if (jsTestFile.exists()) return;
183 String original = readFile(PATH_WEBVIEW_PREFIX + "resources/js-test.js");
184 writeFile(PATH_BLINK_PREFIX + "resources/js-test.js", original, false);
188 * Reads a file and returns it's contents as string.
190 private static String readFile(String fileName) throws IOException {
191 FileInputStream inputStream = new FileInputStream(new File(fileName));
192 try {
193 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
194 try {
195 StringBuilder contents = new StringBuilder();
196 String line;
198 while ((line = reader.readLine()) != null) {
199 contents.append(line);
200 contents.append("\n");
202 return contents.toString();
203 } finally {
204 reader.close();
206 } finally {
207 inputStream.close();
212 * Writes a file with the given fileName and contents. If overwrite is true overwrites any
213 * exisiting file with the same file name. If the file does not exist any intermediate
214 * required directories are created.
216 private static void writeFile(final String fileName, final String contents, boolean overwrite)
217 throws FileNotFoundException, IOException {
218 File fileOut = new File(fileName);
220 if (fileOut.exists() && !overwrite) {
221 return;
224 String absolutePath = fileOut.getAbsolutePath();
225 File filePath = new File(absolutePath.substring(0, absolutePath.lastIndexOf("/")));
227 if (!filePath.exists()) {
228 if (!filePath.mkdirs())
229 throw new IOException("failed to create directories: " + filePath);
232 FileOutputStream outputStream = new FileOutputStream(fileOut);
233 try {
234 outputStream.write(contents.getBytes());
235 } finally {
236 outputStream.close();
240 private HashMap<String, HashSet<String>> buildHashMap(String contents) {
241 String[] lineByLine = contents.split("\\n");
243 HashSet subset = null;
244 HashMap<String, HashSet<String>> interfaces = new HashMap<String, HashSet<String>>();
245 for (String line : lineByLine) {
246 String s = trimAndRemoveComments(line);
247 if (s.startsWith("interface")) {
248 subset = new HashSet();
249 interfaces.put(s, subset);
250 } else if (interfaceProperty(s) && subset != null) {
251 subset.add(s);
254 return interfaces;
257 private String trimAndRemoveComments(String line) {
258 String s = line.trim();
259 int commentIndex = s.indexOf("#"); // remove any potential comments
260 return (commentIndex >= 0) ? s.substring(0, commentIndex).trim() : s;
263 private boolean interfaceProperty(String s) {
264 return s.startsWith("getter") || s.startsWith("setter")
265 || s.startsWith("method") || s.startsWith("attribute");