OLD | NEW |
| (Empty) |
1 // Copyright 2017 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.chrome.browser.vr_shell; | |
6 | |
7 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_CHECK_INTERVAL_L
ONG_MS; | |
8 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_CHECK_INTERVAL_S
HORT_MS; | |
9 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_TIMEOUT_LONG_MS; | |
10 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_TIMEOUT_SHORT_MS
; | |
11 | |
12 import org.chromium.base.Log; | |
13 import org.chromium.base.test.util.UrlUtils; | |
14 import org.chromium.chrome.test.ChromeTabbedActivityTestBase; | |
15 import org.chromium.content.browser.test.util.ClickUtils; | |
16 import org.chromium.content.browser.test.util.Criteria; | |
17 import org.chromium.content.browser.test.util.CriteriaHelper; | |
18 import org.chromium.content.browser.test.util.JavaScriptUtils; | |
19 import org.chromium.content_public.browser.WebContents; | |
20 | |
21 import java.util.concurrent.Callable; | |
22 import java.util.concurrent.TimeUnit; | |
23 import java.util.concurrent.TimeoutException; | |
24 | |
25 /** | |
26 * This is a workaround for testing aspects of WebVR that aren't testable with | |
27 * WebVR's mocked layout tests, such as E2E tests. | |
28 * | |
29 * The general test flow is: | |
30 * - Load the HTML file containing the test, which: | |
31 * - Loads the WebVR boilerplate code and some test functions | |
32 * - Sets up common elements like the canvas and synchronization variable | |
33 * - Sets up any steps that need to be triggered by the Java code | |
34 * - Check if any VRDisplay objects were found and fail the test if it doesn't | |
35 * match what we expect for that test | |
36 * - Repeat: | |
37 * - Run any necessary Java-side code, e.g. trigger a user action | |
38 * - Trigger the next JavaScript test step and wait for it to finish | |
39 * | |
40 * The JavaScript code will automatically process test results once all | |
41 * testharness.js tests are done, just like in layout tests. Once the results | |
42 * are processed, the JavaScript code will automatically signal the Java code, | |
43 * which can then grab the results and pass/fail the instrumentation test. | |
44 */ | |
45 public class VrTestBase extends ChromeTabbedActivityTestBase { | |
46 private static final String TAG = "VrTestBase"; | |
47 protected static final String TEST_DIR = "chrome/test/data/android/webvr_ins
trumentation"; | |
48 protected static final int PAGE_LOAD_TIMEOUT_S = 10; | |
49 | |
50 protected WebContents mWebContents; | |
51 | |
52 @Override | |
53 protected void setUp() throws Exception { | |
54 super.setUp(); | |
55 mWebContents = getActivity().getActivityTab().getWebContents(); | |
56 } | |
57 | |
58 @Override | |
59 public void startMainActivity() throws InterruptedException { | |
60 startMainActivityOnBlankPage(); | |
61 } | |
62 | |
63 /** | |
64 * Gets the file:// URL to the test file | |
65 * @param testName The name of the test whose file will be retrieved | |
66 * @return The file:// URL to the specified test file | |
67 */ | |
68 protected static String getHtmlTestFile(String testName) { | |
69 return "file://" + UrlUtils.getIsolatedTestFilePath(TEST_DIR) + "/html/"
+ testName | |
70 + ".html"; | |
71 } | |
72 | |
73 /** | |
74 * Blocks until the promise returned by nagivator.getVRDisplays() resolves, | |
75 * then checks whether a VRDisplay was actually found. | |
76 * @param webContents The WebContents to run the JavaScript through | |
77 * @return Whether a VRDisplay was found | |
78 */ | |
79 protected boolean vrDisplayFound(WebContents webContents) { | |
80 pollJavaScriptBoolean("vrDisplayPromiseDone", POLL_TIMEOUT_SHORT_MS, web
Contents); | |
81 return !runJavaScriptOrFail("vrDisplay", POLL_TIMEOUT_SHORT_MS, webConte
nts).equals("null"); | |
82 } | |
83 | |
84 /** | |
85 * Use to tap in the middle of the screen, triggering the canvas' onclick | |
86 * to fulfil WebVR's gesture requirement for presenting. | |
87 */ | |
88 protected void enterVrTap() { | |
89 ClickUtils.mouseSingleClickView( | |
90 getInstrumentation(), getActivity().getWindow().getDecorView().g
etRootView()); | |
91 } | |
92 | |
93 /** | |
94 * Taps in the middle of the screen then waits for the JavaScript step to fi
nish. | |
95 * @param webContents The WebContents for the tab the JavaScript step is in | |
96 */ | |
97 protected void enterVrTapAndWait(WebContents webContents) { | |
98 enterVrTap(); | |
99 waitOnJavaScriptStep(webContents); | |
100 } | |
101 | |
102 /** | |
103 * Use to simulate a Daydream View NFC scan without blocking afterwards | |
104 */ | |
105 protected void simNfcScan() { | |
106 VrUtils.simNfc(getActivity()); | |
107 } | |
108 | |
109 /** | |
110 * Simulate an NFC scan and wait for the JavaScript code in the given | |
111 * WebContents to signal that it is done with the step. | |
112 * @param webContents The WebContents for the JavaScript that will be polled | |
113 */ | |
114 protected void simNfcScanAndWait(WebContents webContents) { | |
115 simNfcScan(); | |
116 waitOnJavaScriptStep(webContents); | |
117 } | |
118 | |
119 /** | |
120 * Helper function to run the given JavaScript, return the return value, | |
121 * and fail if a timeout/interrupt occurs so we don't have to catch or | |
122 * declare exceptions all the time. | |
123 * @param js The JavaScript to run | |
124 * @param timeout The timeout in milliseconds before a failure | |
125 * @param webContents The WebContents object to run the JavaScript in | |
126 * @return The return value of the JavaScript | |
127 */ | |
128 protected String runJavaScriptOrFail(String js, int timeout, WebContents web
Contents) { | |
129 try { | |
130 return JavaScriptUtils.executeJavaScriptAndWaitForResult( | |
131 webContents, js, timeout, TimeUnit.MILLISECONDS); | |
132 } catch (InterruptedException | TimeoutException e) { | |
133 fail("Fatal interruption or timeout running JavaScript: " + js); | |
134 } | |
135 return "Not reached"; | |
136 } | |
137 | |
138 /** | |
139 * Ends the test harness test and checks whether there it passed | |
140 * @param webContents The WebContents for the tab to check results in | |
141 * @return "Passed" if test passed, String with failure reason otherwise | |
142 */ | |
143 protected String checkResults(WebContents webContents) { | |
144 if (runJavaScriptOrFail("testPassed", POLL_TIMEOUT_SHORT_MS, webContents
).equals("true")) { | |
145 return "Passed"; | |
146 } | |
147 return runJavaScriptOrFail("resultString", POLL_TIMEOUT_SHORT_MS, webCon
tents); | |
148 } | |
149 | |
150 /** | |
151 * Helper function to end the test harness test and assert that it passed, | |
152 * setting the failure reason as the description if it didn't. | |
153 * @param webContents The WebContents for the tab to check test results in | |
154 */ | |
155 protected void endTest(WebContents webContents) { | |
156 assertEquals("Passed", checkResults(webContents)); | |
157 } | |
158 | |
159 /** | |
160 * Polls the provided JavaScript boolean until the timeout is reached or | |
161 * the boolean is true. | |
162 * @param boolName The name of the JavaScript boolean or expression to poll | |
163 * @param timeoutMs The polling timeout in milliseconds | |
164 * @param webContents The WebContents to run the JavaScript through | |
165 * @return True if the boolean evaluated to true, false if timed out | |
166 */ | |
167 protected boolean pollJavaScriptBoolean( | |
168 final String boolName, int timeoutMs, final WebContents webContents)
{ | |
169 try { | |
170 CriteriaHelper.pollInstrumentationThread(Criteria.equals(true, new C
allable<Boolean>() { | |
171 @Override | |
172 public Boolean call() { | |
173 String result = "false"; | |
174 try { | |
175 result = JavaScriptUtils.executeJavaScriptAndWaitForResu
lt(webContents, | |
176 boolName, POLL_CHECK_INTERVAL_SHORT_MS, TimeUnit
.MILLISECONDS); | |
177 } catch (InterruptedException | TimeoutException e) { | |
178 // Expected to happen regularly, do nothing | |
179 } | |
180 return Boolean.parseBoolean(result); | |
181 } | |
182 }), timeoutMs, POLL_CHECK_INTERVAL_LONG_MS); | |
183 } catch (AssertionError e) { | |
184 Log.d(TAG, "pollJavaScriptBoolean() timed out"); | |
185 return false; | |
186 } | |
187 return true; | |
188 } | |
189 | |
190 /** | |
191 * Waits for a JavaScript step to finish, asserting that the step finished | |
192 * instead of timing out. | |
193 * @param webContents The WebContents for the tab the JavaScript step is in | |
194 */ | |
195 protected void waitOnJavaScriptStep(WebContents webContents) { | |
196 assertTrue("Polling JavaScript boolean javascriptDone timed out", | |
197 pollJavaScriptBoolean("javascriptDone", POLL_TIMEOUT_LONG_MS, we
bContents)); | |
198 // Reset the synchronization boolean | |
199 runJavaScriptOrFail("javascriptDone = false", POLL_TIMEOUT_SHORT_MS, web
Contents); | |
200 } | |
201 | |
202 /** | |
203 * Executes a JavaScript step function using the given WebContents. | |
204 * @param stepFunction The JavaScript step function to call | |
205 * @param webContents The WebContents for the tab the JavaScript is in | |
206 */ | |
207 protected void executeStepAndWait(String stepFunction, WebContents webConten
ts) { | |
208 // Run the step and block | |
209 JavaScriptUtils.executeJavaScript(webContents, stepFunction); | |
210 waitOnJavaScriptStep(webContents); | |
211 } | |
212 } | |
OLD | NEW |