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
;
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
;
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);
52 protected void setUp() throws Exception
{
54 mTestActivity
= (WebViewLayoutTestActivity
) getActivity();
58 protected void tearDown() throws Exception
{
59 mTestActivity
.finish();
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
{
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
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
)
143 runTest(PATH_WEBVIEW_PREFIX
+ fileName
, PATH_WEBVIEW_PREFIX
+ fileNameExpected
);
146 private void runBlinkLayoutTest(final String fileName
, final String fileNameExpected
)
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());
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() {
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
));
193 BufferedReader reader
= new BufferedReader(new InputStreamReader(inputStream
));
195 StringBuilder contents
= new StringBuilder();
198 while ((line
= reader
.readLine()) != null) {
199 contents
.append(line
);
200 contents
.append("\n");
202 return contents
.toString();
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
) {
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
);
234 outputStream
.write(contents
.getBytes());
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) {
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");