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.
4 
5 package org.chromium.webview_shell;
6 
7 import android.os.Environment;
8 import android.test.ActivityInstrumentationTestCase2;
9 import android.util.Log;
10 
11 import java.io.BufferedReader;
12 import java.io.File;
13 import java.io.FileInputStream;
14 import java.io.FileNotFoundException;
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 import java.io.InputStreamReader;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 
21 /**
22  * Tests running end-to-end layout tests.
23  */
24 public class WebViewLayoutTest
25         extends ActivityInstrumentationTestCase2<WebViewLayoutTestActivity> {
26 
27     private static final String TAG = "WebViewLayoutTest";
28 
29     private static final String EXTERNAL_PREFIX =
30             Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
31     private static final String BASE_WEBVIEW_TEST_PATH = "android_webview/tools/WebViewShell/test/";
32     private static final String BASE_BLINK_TEST_PATH = "third_party/WebKit/LayoutTests/";
33     private static final String PATH_WEBVIEW_PREFIX = EXTERNAL_PREFIX + BASE_WEBVIEW_TEST_PATH;
34     private static final String PATH_BLINK_PREFIX = EXTERNAL_PREFIX + BASE_BLINK_TEST_PATH;
35 
36     private static final long TIMEOUT_SECONDS = 20;
37 
38     private WebViewLayoutTestActivity mTestActivity;
39 
WebViewLayoutTest()40     public WebViewLayoutTest() {
41         super(WebViewLayoutTestActivity.class);
42     }
43 
44     @Override
setUp()45     protected void setUp() throws Exception {
46         super.setUp();
47         mTestActivity = (WebViewLayoutTestActivity) getActivity();
48     }
49 
50     @Override
tearDown()51     protected void tearDown() throws Exception {
52         mTestActivity.finish();
53         super.tearDown();
54     }
55 
56     @Override
getInstrumentation()57     public WebViewLayoutTestRunner getInstrumentation() {
58         return (WebViewLayoutTestRunner) super.getInstrumentation();
59     }
60 
testSimple()61     public void testSimple() throws Exception {
62         runWebViewLayoutTest("experimental/basic-logging.html",
63                              "experimental/basic-logging-expected.txt");
64     }
65 
testGlobalInterface()66     public void testGlobalInterface() throws Exception {
67         runBlinkLayoutTest("webexposed/global-interface-listing.html",
68                            "webexposed/global-interface-listing-expected.txt");
69     }
70 
71     // test helper methods
72 
runWebViewLayoutTest(final String fileName, final String fileNameExpected)73     private void runWebViewLayoutTest(final String fileName, final String fileNameExpected)
74             throws Exception {
75         runTest(PATH_WEBVIEW_PREFIX + fileName, PATH_WEBVIEW_PREFIX + fileNameExpected);
76     }
77 
runBlinkLayoutTest(final String fileName, final String fileNameExpected)78     private void runBlinkLayoutTest(final String fileName, final String fileNameExpected)
79             throws Exception {
80         ensureJsTestCopied();
81         runTest(PATH_BLINK_PREFIX + fileName, PATH_WEBVIEW_PREFIX + fileNameExpected);
82     }
83 
runTest(final String fileName, final String fileNameExpected)84     private void runTest(final String fileName, final String fileNameExpected)
85             throws FileNotFoundException, IOException, InterruptedException, TimeoutException {
86         loadUrlWebViewAsync("file://" + fileName, mTestActivity);
87 
88         if (getInstrumentation().isRebaseline()) {
89             // this is the rebaseline process
90             mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
91             String result = mTestActivity.getTestResult();
92             writeFile(fileNameExpected, result, true);
93             Log.i(TAG, "file: " + fileNameExpected + " --> rebaselined, length=" + result.length());
94         } else {
95             String expected = readFile(fileNameExpected);
96             mTestActivity.waitForFinish(TIMEOUT_SECONDS, TimeUnit.SECONDS);
97             String result = mTestActivity.getTestResult();
98             assertEquals(expected, result);
99         }
100     }
101 
loadUrlWebViewAsync(final String fileUrl, final WebViewLayoutTestActivity activity)102     private void loadUrlWebViewAsync(final String fileUrl,
103             final WebViewLayoutTestActivity activity) {
104         getInstrumentation().runOnMainSync(new Runnable() {
105             @Override
106             public void run() {
107                 activity.loadUrl(fileUrl);
108             }
109         });
110     }
111 
ensureJsTestCopied()112     private static void ensureJsTestCopied() throws IOException {
113         File jsTestFile = new File(PATH_BLINK_PREFIX + "resources/js-test.js");
114         if (jsTestFile.exists()) return;
115         String original = readFile(PATH_WEBVIEW_PREFIX + "resources/js-test.js");
116         writeFile(PATH_BLINK_PREFIX + "resources/js-test.js", original, false);
117     }
118 
119     /**
120      * Reads a file and returns it's contents as string.
121      */
readFile(String fileName)122     private static String readFile(String fileName) throws IOException {
123         FileInputStream inputStream = new FileInputStream(new File(fileName));
124         try {
125             BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
126             try {
127                 StringBuilder contents = new StringBuilder();
128                 String line;
129 
130                 while ((line = reader.readLine()) != null) {
131                     contents.append(line);
132                     contents.append("\n");
133                 }
134                 return contents.toString();
135             } finally {
136                 reader.close();
137             }
138         } finally {
139             inputStream.close();
140         }
141     }
142 
143     /**
144      * Writes a file with the given fileName and contents. If overwrite is true overwrites any
145      * exisiting file with the same file name. If the file does not exist any intermediate
146      * required directories are created.
147      */
writeFile(final String fileName, final String contents, boolean overwrite)148     private static void writeFile(final String fileName, final String contents, boolean overwrite)
149             throws FileNotFoundException, IOException {
150         File fileOut = new File(fileName);
151 
152         if (fileOut.exists() && !overwrite) {
153             return;
154         }
155 
156         String absolutePath = fileOut.getAbsolutePath();
157         File filePath = new File(absolutePath.substring(0, absolutePath.lastIndexOf("/")));
158 
159         if (!filePath.exists()) {
160             if (!filePath.mkdirs())
161                 throw new IOException("failed to create directories: " + filePath);
162         }
163 
164         FileOutputStream outputStream = new FileOutputStream(fileOut);
165         try {
166             outputStream.write(contents.getBytes());
167         } finally {
168             outputStream.close();
169         }
170     }
171 }
172