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