OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_TIMEOUT_LONG_MS; | 7 import static org.chromium.chrome.browser.vr_shell.VrUtils.POLL_TIMEOUT_LONG_MS; |
8 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_DAYDREAM; | 8 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_DAYDREAM; |
9 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_NON_DAYDREAM; | 9 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_D
EVICE_NON_DAYDREAM; |
10 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_V
IEWER_DAYDREAM; | 10 import static org.chromium.chrome.test.util.ChromeRestriction.RESTRICTION_TYPE_V
IEWER_DAYDREAM; |
11 | 11 |
12 import android.content.pm.ActivityInfo; | 12 import android.content.pm.ActivityInfo; |
| 13 import android.support.test.InstrumentationRegistry; |
13 import android.support.test.filters.MediumTest; | 14 import android.support.test.filters.MediumTest; |
14 import android.support.test.filters.SmallTest; | 15 import android.support.test.filters.SmallTest; |
15 import android.view.ViewGroup; | 16 import android.view.ViewGroup; |
16 | 17 |
| 18 import org.junit.Assert; |
| 19 import org.junit.Before; |
| 20 import org.junit.Rule; |
| 21 import org.junit.Test; |
| 22 import org.junit.runner.RunWith; |
| 23 |
17 import org.chromium.base.ThreadUtils; | 24 import org.chromium.base.ThreadUtils; |
18 import org.chromium.base.test.util.CommandLineFlags; | 25 import org.chromium.base.test.util.CommandLineFlags; |
19 import org.chromium.base.test.util.Feature; | 26 import org.chromium.base.test.util.Feature; |
20 import org.chromium.base.test.util.Restriction; | 27 import org.chromium.base.test.util.Restriction; |
21 import org.chromium.base.test.util.RetryOnFailure; | 28 import org.chromium.base.test.util.RetryOnFailure; |
22 import org.chromium.chrome.R; | 29 import org.chromium.chrome.R; |
| 30 import org.chromium.chrome.browser.ChromeSwitches; |
| 31 import org.chromium.chrome.browser.ChromeTabbedActivity; |
23 import org.chromium.chrome.browser.compositor.CompositorViewHolder; | 32 import org.chromium.chrome.browser.compositor.CompositorViewHolder; |
24 import org.chromium.chrome.browser.tabmodel.TabModelSelector; | 33 import org.chromium.chrome.browser.tabmodel.TabModelSelector; |
| 34 import org.chromium.chrome.test.ChromeActivityTestRule; |
| 35 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
| 36 import org.chromium.chrome.test.ChromeTabbedActivityTestRule; |
25 import org.chromium.chrome.test.util.RenderUtils.ViewRenderer; | 37 import org.chromium.chrome.test.util.RenderUtils.ViewRenderer; |
26 import org.chromium.content.browser.ContentViewCore; | 38 import org.chromium.content.browser.ContentViewCore; |
27 import org.chromium.content.browser.test.util.Criteria; | 39 import org.chromium.content.browser.test.util.Criteria; |
28 import org.chromium.content.browser.test.util.CriteriaHelper; | 40 import org.chromium.content.browser.test.util.CriteriaHelper; |
29 | 41 |
30 import java.io.IOException; | 42 import java.io.IOException; |
31 import java.util.concurrent.Callable; | 43 import java.util.concurrent.Callable; |
32 import java.util.concurrent.TimeoutException; | 44 import java.util.concurrent.TimeoutException; |
33 import java.util.concurrent.atomic.AtomicReference; | 45 import java.util.concurrent.atomic.AtomicReference; |
34 | 46 |
35 /** | 47 /** |
36 * End-to-end tests for VR browsing, aka "VR Shell". This may require | 48 * End-to-end tests for VR browsing, aka "VR Shell". This may require |
37 * interacting with WebVR in addition to the VR browser, so inherit from | 49 * interacting with WebVR in addition to the VR browser, so inherit from |
38 * VrTestBase for the WebVR test framework. | 50 * VrTestBase for the WebVR test framework. |
39 */ | 51 */ |
40 @CommandLineFlags.Add("enable-features=VrShell") | 52 @RunWith(ChromeJUnit4ClassRunner.class) |
41 public class VrShellTest extends VrTestBase { | 53 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, |
| 54 ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, "enable-features
=VrShell"}) |
| 55 public class VrShellTest { |
| 56 @Rule |
| 57 public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActi
vityTestRule(); |
| 58 |
42 private static final String GOLDEN_DIR = | 59 private static final String GOLDEN_DIR = |
43 "chrome/test/data/android/render_tests"; | 60 "chrome/test/data/android/render_tests"; |
44 | 61 |
45 private VrShellDelegate mDelegate; | 62 private VrShellDelegate mDelegate; |
46 private ViewRenderer mViewRenderer; | 63 private ViewRenderer mViewRenderer; |
47 | 64 |
48 @Override | 65 @Before |
49 protected void setUp() throws Exception { | 66 public void setUp() throws Exception { |
50 super.setUp(); | 67 mActivityTestRule.startMainActivityOnBlankPage(); |
| 68 mViewRenderer = new ViewRenderer( |
| 69 mActivityTestRule.getActivity(), GOLDEN_DIR, this.getClass().get
SimpleName()); |
51 mDelegate = VrUtils.getVrShellDelegateInstance(); | 70 mDelegate = VrUtils.getVrShellDelegateInstance(); |
52 } | 71 } |
53 | 72 |
54 @Override | |
55 public void startMainActivity() throws InterruptedException { | |
56 startMainActivityOnBlankPage(); | |
57 mViewRenderer = new ViewRenderer(getActivity(), | |
58 GOLDEN_DIR, this.getClass().getSimpleName()); | |
59 } | |
60 | |
61 private void enterExitVrMode(boolean supported) { | 73 private void enterExitVrMode(boolean supported) { |
62 MockVrDaydreamApi mockApi = new MockVrDaydreamApi(); | 74 MockVrDaydreamApi mockApi = new MockVrDaydreamApi(); |
63 if (!supported) { | 75 if (!supported) { |
64 mDelegate.overrideDaydreamApiForTesting(mockApi); | 76 mDelegate.overrideDaydreamApiForTesting(mockApi); |
65 } | 77 } |
66 VrUtils.forceEnterVr(); | 78 VrUtils.forceEnterVr(); |
67 if (supported) { | 79 if (supported) { |
68 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); | 80 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); |
69 assertTrue(VrShellDelegate.isInVr()); | 81 Assert.assertTrue(VrShellDelegate.isInVr()); |
70 } else { | 82 } else { |
71 assertFalse(mockApi.getLaunchInVrCalled()); | 83 Assert.assertFalse(mockApi.getLaunchInVrCalled()); |
72 assertFalse(VrShellDelegate.isInVr()); | 84 Assert.assertFalse(VrShellDelegate.isInVr()); |
73 } | 85 } |
74 VrUtils.forceExitVr(mDelegate); | 86 VrUtils.forceExitVr(mDelegate); |
75 assertFalse(VrShellDelegate.isInVr()); | 87 Assert.assertFalse(VrShellDelegate.isInVr()); |
76 } | 88 } |
77 | 89 |
78 private void enterExitVrModeImage(boolean supported) throws IOException { | 90 private void enterExitVrModeImage(boolean supported) throws IOException { |
79 int prevOrientation = getActivity().getRequestedOrientation(); | 91 ChromeTabbedActivity activity = mActivityTestRule.getActivity(); |
80 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LA
NDSCAPE); | 92 int prevOrientation = activity.getRequestedOrientation(); |
81 getInstrumentation().waitForIdleSync(); | 93 mActivityTestRule.getActivity().setRequestedOrientation( |
| 94 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
| 95 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
82 mViewRenderer.renderAndCompare( | 96 mViewRenderer.renderAndCompare( |
83 getActivity().getWindow().getDecorView().getRootView(), | 97 activity.getWindow().getDecorView().getRootView(), "blank_page")
; |
84 "blank_page"); | |
85 | 98 |
86 VrUtils.forceEnterVr(); | 99 VrUtils.forceEnterVr(); |
87 // Currently, screenshots only show the static UI overlay, not the | 100 // Currently, screenshots only show the static UI overlay, not the |
88 // actual content. Thus, 1:1 pixel checking is reliable until a | 101 // actual content. Thus, 1:1 pixel checking is reliable until a |
89 // way to take screenshots of VR content is added, in which case | 102 // way to take screenshots of VR content is added, in which case |
90 // % similarity or some other method will need to be used. We're | 103 // % similarity or some other method will need to be used. We're |
91 // assuming that if the UI overlay is visible, then the device has | 104 // assuming that if the UI overlay is visible, then the device has |
92 // successfully entered VR mode. | 105 // successfully entered VR mode. |
93 if (supported) { | 106 if (supported) { |
94 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); | 107 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); |
95 mViewRenderer.renderAndCompare( | 108 mViewRenderer.renderAndCompare( |
96 getActivity().getWindow().getDecorView().getRootView(), | 109 activity.getWindow().getDecorView().getRootView(), "vr_enter
ed"); |
97 "vr_entered"); | |
98 } else { | 110 } else { |
99 // TODO(bsheedy): Find a good way to wait before taking a screenshot | 111 // TODO(bsheedy): Find a good way to wait before taking a screenshot |
100 // when running on an unsupported device | 112 // when running on an unsupported device |
101 mViewRenderer.renderAndCompare( | 113 mViewRenderer.renderAndCompare( |
102 getActivity().getWindow().getDecorView().getRootView(), | 114 activity.getWindow().getDecorView().getRootView(), "blank_pa
ge"); |
103 "blank_page"); | |
104 } | 115 } |
105 | 116 |
106 VrUtils.forceExitVr(mDelegate); | 117 VrUtils.forceExitVr(mDelegate); |
107 getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LA
NDSCAPE); | 118 activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCA
PE); |
108 getInstrumentation().waitForIdleSync(); | 119 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
109 mViewRenderer.renderAndCompare( | 120 mViewRenderer.renderAndCompare( |
110 getActivity().getWindow().getDecorView().getRootView(), | 121 activity.getWindow().getDecorView().getRootView(), "blank_page")
; |
111 "blank_page"); | |
112 | 122 |
113 getActivity().setRequestedOrientation(prevOrientation); | 123 activity.setRequestedOrientation(prevOrientation); |
114 } | 124 } |
115 | 125 |
116 private void enterVrModeNfc(boolean supported) { | 126 private void enterVrModeNfc(boolean supported) { |
117 getInstrumentation().waitForIdleSync(); | 127 InstrumentationRegistry.getInstrumentation().waitForIdleSync(); |
118 VrUtils.simNfc(getActivity()); | 128 VrUtils.simNfc(mActivityTestRule.getActivity()); |
119 if (supported) { | 129 if (supported) { |
120 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); | 130 VrUtils.waitForVrSupported(POLL_TIMEOUT_LONG_MS); |
121 assertTrue(VrShellDelegate.isInVr()); | 131 Assert.assertTrue(VrShellDelegate.isInVr()); |
122 } else { | 132 } else { |
123 assertFalse(VrShellDelegate.isInVr()); | 133 Assert.assertFalse(VrShellDelegate.isInVr()); |
124 } | 134 } |
125 VrUtils.forceExitVr(mDelegate); | 135 VrUtils.forceExitVr(mDelegate); |
126 // TODO(bsheedy): Figure out why NFC tests cause the next test to fail | 136 // TODO(bsheedy): Figure out why NFC tests cause the next test to fail |
127 // to enter VR unless we sleep for some amount of time after exiting VR | 137 // to enter VR unless we sleep for some amount of time after exiting VR |
128 // in the NFC test | 138 // in the NFC test |
129 } | 139 } |
130 | 140 |
131 /** | 141 /** |
132 * Verifies that browser successfully enters VR mode when Daydream headset | 142 * Verifies that browser successfully enters VR mode when Daydream headset |
133 * NFC tag is scanned on a Daydream-ready device. Requires that the phone | 143 * NFC tag is scanned on a Daydream-ready device. Requires that the phone |
134 * is unlocked. | 144 * is unlocked. |
135 */ | 145 */ |
| 146 @Test |
136 @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYD
REAM}) | 147 @Restriction({RESTRICTION_TYPE_DEVICE_DAYDREAM, RESTRICTION_TYPE_VIEWER_DAYD
REAM}) |
137 @MediumTest | 148 @MediumTest |
138 public void testSimNfcSupported() { | 149 public void testSimNfcSupported() { |
139 enterVrModeNfc(true); | 150 enterVrModeNfc(true); |
140 } | 151 } |
141 | 152 |
142 /** | 153 /** |
143 * Verifies that the browser does not enter VR mode on Non-Daydream-ready | 154 * Verifies that the browser does not enter VR mode on Non-Daydream-ready |
144 * devices when the Daydream headset NFC tag is scanned. | 155 * devices when the Daydream headset NFC tag is scanned. |
145 */ | 156 */ |
| 157 @Test |
146 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) | 158 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) |
147 @SmallTest | 159 @SmallTest |
148 public void testSimNfcUnsupported() { | 160 public void testSimNfcUnsupported() { |
149 enterVrModeNfc(false); | 161 enterVrModeNfc(false); |
150 } | 162 } |
151 | 163 |
152 /** | 164 /** |
153 * Verifies that browser successfully enters and exits VR mode when told to | 165 * Verifies that browser successfully enters and exits VR mode when told to |
154 * on Daydream-ready devices. Requires that the phone is unlocked. | 166 * on Daydream-ready devices. Requires that the phone is unlocked. |
155 */ | 167 */ |
| 168 @Test |
156 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) | 169 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) |
157 @SmallTest | 170 @SmallTest |
158 public void testEnterExitVrModeSupported() { | 171 public void testEnterExitVrModeSupported() { |
159 enterExitVrMode(true); | 172 enterExitVrMode(true); |
160 } | 173 } |
161 | 174 |
162 /** | 175 /** |
163 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s. | 176 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s. |
164 */ | 177 */ |
| 178 @Test |
165 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) | 179 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) |
166 @SmallTest | 180 @SmallTest |
167 public void testEnterExitVrModeUnsupported() { | 181 public void testEnterExitVrModeUnsupported() { |
168 enterExitVrMode(false); | 182 enterExitVrMode(false); |
169 } | 183 } |
170 | 184 |
171 /** | 185 /** |
172 * Verifies that browser successfully enters and exits VR mode when told to | 186 * Verifies that browser successfully enters and exits VR mode when told to |
173 * on Daydream-ready devices via a screendiffing check. | 187 * on Daydream-ready devices via a screendiffing check. |
174 * Requires that the phone is unlocked. | 188 * Requires that the phone is unlocked. |
175 */ | 189 */ |
| 190 @Test |
176 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) | 191 @Restriction(RESTRICTION_TYPE_DEVICE_DAYDREAM) |
177 @Feature("RenderTest") | 192 @Feature("RenderTest") |
178 @MediumTest | 193 @MediumTest |
179 public void testEnterExitVrModeSupportedImage() throws IOException { | 194 public void testEnterExitVrModeSupportedImage() throws IOException { |
180 enterExitVrModeImage(true); | 195 enterExitVrModeImage(true); |
181 } | 196 } |
182 | 197 |
183 /** | 198 /** |
184 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s | 199 * Verifies that browser does not enter VR mode on Non-Daydream-ready device
s |
185 * via a screendiffing check. Requires that the phone is unlocked. | 200 * via a screendiffing check. Requires that the phone is unlocked. |
186 */ | 201 */ |
| 202 @Test |
187 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) | 203 @Restriction(RESTRICTION_TYPE_DEVICE_NON_DAYDREAM) |
188 @Feature("RenderTest") | 204 @Feature("RenderTest") |
189 @MediumTest | 205 @MediumTest |
190 public void testEnterExitVrModeUnsupportedImage() throws IOException { | 206 public void testEnterExitVrModeUnsupportedImage() throws IOException { |
191 enterExitVrModeImage(false); | 207 enterExitVrModeImage(false); |
192 } | 208 } |
193 | 209 |
194 /** | 210 /** |
195 * Verify that resizing the CompositorViewHolder does not cause the current
tab to resize while | 211 * Verify that resizing the CompositorViewHolder does not cause the current
tab to resize while |
196 * the CompositorViewHolder is detached from the TabModelSelector. See crbug
.com/680240. | 212 * the CompositorViewHolder is detached from the TabModelSelector. See crbug
.com/680240. |
197 * @throws InterruptedException | 213 * @throws InterruptedException |
198 * @throws TimeoutException | 214 * @throws TimeoutException |
199 */ | 215 */ |
| 216 @Test |
200 @SmallTest | 217 @SmallTest |
201 @RetryOnFailure | 218 @RetryOnFailure |
202 public void testResizeWithCompositorViewHolderDetached() | 219 public void testResizeWithCompositorViewHolderDetached() |
203 throws InterruptedException, TimeoutException { | 220 throws InterruptedException, TimeoutException { |
204 final AtomicReference<TabModelSelector> selector = new AtomicReference<>
(); | 221 final AtomicReference<TabModelSelector> selector = new AtomicReference<>
(); |
205 final AtomicReference<Integer> oldWidth = new AtomicReference<>(); | 222 final AtomicReference<Integer> oldWidth = new AtomicReference<>(); |
206 final int testWidth = 123; | 223 final int testWidth = 123; |
207 final ContentViewCore cvc = getActivity().getActivityTab().getActiveCont
entViewCore(); | 224 final ContentViewCore cvc = |
| 225 mActivityTestRule.getActivity().getActivityTab().getActiveConten
tViewCore(); |
208 | 226 |
209 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 227 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
210 @Override | 228 @Override |
211 public void run() { | 229 public void run() { |
212 CompositorViewHolder compositorViewHolder = (CompositorViewHolde
r) | 230 CompositorViewHolder compositorViewHolder = |
213 getActivity().findViewById(R.id.compositor_view_holder); | 231 (CompositorViewHolder) mActivityTestRule.getActivity().f
indViewById( |
| 232 R.id.compositor_view_holder); |
214 selector.set(compositorViewHolder.detachForVr()); | 233 selector.set(compositorViewHolder.detachForVr()); |
215 oldWidth.set(cvc.getViewportWidthPix()); | 234 oldWidth.set(cvc.getViewportWidthPix()); |
216 | 235 |
217 ViewGroup.LayoutParams layoutParams = compositorViewHolder.getLa
youtParams(); | 236 ViewGroup.LayoutParams layoutParams = compositorViewHolder.getLa
youtParams(); |
218 layoutParams.width = testWidth; | 237 layoutParams.width = testWidth; |
219 layoutParams.height = 456; | 238 layoutParams.height = 456; |
220 compositorViewHolder.requestLayout(); | 239 compositorViewHolder.requestLayout(); |
221 } | 240 } |
222 }); | 241 }); |
223 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { | 242 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { |
224 @Override | 243 @Override |
225 public Integer call() { | 244 public Integer call() { |
226 return getActivity().findViewById(R.id.compositor_view_holder).g
etMeasuredWidth(); | 245 return mActivityTestRule.getActivity() |
| 246 .findViewById(R.id.compositor_view_holder) |
| 247 .getMeasuredWidth(); |
227 } | 248 } |
228 })); | 249 })); |
229 | 250 |
230 assertEquals("Viewport width should not have changed when resizing a det
ached " | 251 Assert.assertEquals("Viewport width should not have changed when resizin
g a detached " |
231 + "CompositorViewHolder", | 252 + "CompositorViewHolder", |
232 cvc.getViewportWidthPix(), | 253 cvc.getViewportWidthPix(), oldWidth.get().intValue()); |
233 oldWidth.get().intValue()); | |
234 | 254 |
235 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 255 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
236 @Override | 256 @Override |
237 public void run() { | 257 public void run() { |
238 CompositorViewHolder compositorViewHolder = (CompositorViewHolde
r) getActivity() | 258 CompositorViewHolder compositorViewHolder = |
239 .findViewById(R.id.compositor_view_holder); | 259 (CompositorViewHolder) mActivityTestRule.getActivity().f
indViewById( |
| 260 R.id.compositor_view_holder); |
240 compositorViewHolder.onExitVr(selector.get()); | 261 compositorViewHolder.onExitVr(selector.get()); |
241 } | 262 } |
242 }); | 263 }); |
243 | 264 |
244 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { | 265 CriteriaHelper.pollUiThread(Criteria.equals(testWidth, new Callable<Inte
ger>() { |
245 @Override | 266 @Override |
246 public Integer call() { | 267 public Integer call() { |
247 return cvc.getViewportWidthPix(); | 268 return cvc.getViewportWidthPix(); |
248 } | 269 } |
249 })); | 270 })); |
250 } | 271 } |
251 } | 272 } |
OLD | NEW |