File: xr_browser_tests.md

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (198 lines) | stat: -rw-r--r-- 9,396 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# XR Browser Tests

[TOC]

## Introduction

This documentation concerns `xr_browser_test.h`, `xr_browser_test.cc`, and files
that use them or their subclasses.

These files port the framework used by XR instrumentation tests (located in
[`//chrome/android/javatests/src/org/chromium/chrome/browser/vr/`][vr android dir]
and documented in
`//chrome/android/javatests/src/org/chromium/chrome/browser/vr/*.md`) for
use in browser tests in order to test XR features on desktop platforms.

[vr android dir]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr

This is pretty much a direct port, with the same JavaScript/HTML files being
used for both and the Java/C++ code being functionally equivalent to each other,
so the instrumentation test's documentation on writing tests using the framework
is applicable here, too. As such, this documentation only covers any notable
differences between the two implementations.

## Mock XR Device

Any runtime attempting to start an Immersive session needs to add a Mock Device,
as otherwise Android tests will fail due to trying to spawn a new activity,
which currently isn't supported.

## Threading

It is important to be mindful of the threading model within these tests. The
main test thread is the same as the browser's UI thread. On Android, the
device thread is also the browser thread. This configuration makes
it very easy to cause a deadlock in the browser process. To avoid this, any
`MockXRDevice` should run its mojo methods, which are synchronously queried by
the device on the device thread, on a separate thread. Furthermore, using
`base::WaitableEvent` will completely block the thread it is called on. Since
this would block the browser process, `base::WaitableEvent` should not be
used, but rather `base::RunLoop` should be used instead.

## Restrictions

Both the instrumentation tests and browser tests have hardware/software
restrictions - in the case of browser tests, XR is only supported on Windows 8
and later (or Windows 7 with a non-standard patch applied) with a GPU that
supports DirectX 11.1 or on Android, although, several tests exist that don't
actually use XR functionality, and thus don't have these requirements.

Runtime restrictions in browser tests are handled via the macros in
`conditional_skipping.h`. To add a runtime requirement to a test class, simply
append it to the `runtime_requirements_` vector that each class has. The
test setup will automatically skip tests that don't meet all requirements.

One-off skipping within a test can also be done by using the XR_CONDITIONAL_SKIP
macro directly in a test.

The bots can be made to ignore these runtime requirement checks if we expect
the requirements to always be met (and thus we want the tests to fail if they
aren't) via the `--ignore-runtime-requirements` argument. This takes a
comma-separated list of requirements to ignore, or the wildcard (\*) to ignore
all requirements. For example, `--ignore-runtime-requirements=DirectX_11.1`
would cause a test that requires a DirectX 11.1 device to be run even if a
suitable device is not found.

New requirements can be added by adding to the `XrTestRequirement` enum in
`conditional_skipping.h` and adding its associated checking logic in
`conditional_skipping.cc`.

## Command Line Switches

Instrumentation tests are able to add and remove command line switches on a
per-test-case basis using `@CommandLine` annotations, but equivalent
functionality does not exist in browser tests.

Instead, if different command line flags are needed, a new class will need to
be created that extends the correct type of `*BrowserTestBase` and overrides the
flags that are set in its `SetUp` function.

## Compiling And Running

### Windows

The tests are compiled in the `xr_browser_tests` target. This is a combination
of the `xr_browser_tests_binary` target, which is the actual test, and the
`xr_browser_tests_runner` target, which is a wrapper script that ensures special
setup is completed before running the tests.

Once compiled, the tests can be run using the following command line:

`run_xr_browser_tests.py --enable-gpu --test-launcher-jobs=1
--enable-pixel-output-in-tests`

Additional options such as test filtering can be found by running
`xr_browser_tests.exe --help` and `xr_browser_tests.exe --gtest_help`.

Because the "test" is actually a Python wrapper script, you may need to prepend
`python` to the front of the command on Windows if Python file association is
not set up on your machine.

### Android

On Android, the tests are built and run via the `android_browsertests` target.
Note that due to the deployment of a mock OpenXR runtime and writing a JSON file
to: `'/product/etc/openxr/1/active_runtime.json'`, tests must be run on a rooted
device. Because this is a large target, it is recommended to append
`--gtest_filter=*WebXr*` when running the tests.

## Adding New Files

If you are adding a new test or infrastructure file to the target, you'll need
to consider whether it's useful with the `enable_vr` gn arg set to false or not.
If it is, then it should be included in `//chrome/test:xr_browser_tests_common`,
otherwise it should be included in
`//chrome/browser/vr:xr_browser_tests_vr_required`.

If including in `//chrome/test:xr_browser_tests_common`, you may need to hide
some VR-specific functionality in the file behind `#if BUILDFLAG(ENABLE_VR)`.

## Running A Test Multiple Times With Different Runtimes

The macros provided by
[`//chrome/browser/vr/test/multi_class_browser_test.h`][multi class macros]
provide a shorthand method for running a test multiple times with different
classes/runtimes. This is effectively the same as declaring some implementation
function that takes a reference to some base class shared by all the subclasses
you want to run the test with, then having each test call that implementation.

These macros help cut down on boilerplate code, but if you need either:

1. Class-specific setup before running the implementation
2. Different test logic in the implementation depending on the provided class

You should consider using the standard IN_PROC_BROWSER_TEST_F macros instead.
Small snippets of runtime-specific code are acceptable, but if it affects
readability significantly, the tests should probably remain separate.

Most tests simply use the standard `WebXrVrOpenXrBrowserTest` class.
In this case, you can instead use the `WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F`
macro, which only needs to take the test name, further cutting down on
boilerplate code.

You can also use `WEBXR_VR_ALL_RUNTIMES_PLUS_INCOGNITO_BROWSER_TEST_F` if you
want the same functionality as `WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F`, but
also want the test run in Incognito mode in addition to regular Chrome.

[multi class macros]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/multi_class_browser_test.h

## Test Class Names

The test classes that are used to provide feature and runtime-specific setup and
functions are named in the following order:

1. Feature
2. Runtime
3. "BrowserTest"
4. Optional Descriptor/special flags

For example, `WebXrVrOpenXrBrowserTest` is meant for testing the WebXR for VR
feature using the OpenXR runtime with standard flags enabled, i.e. the flags
required for using WebXR and the OpenXR runtime with other runtimes disabled.
`WebXrVrRuntimelessBrowserTestSensorless` on the other hand would be for
testing WebVR for VR without any runtimes and with the orientation sensor
device explicitly disabled.

In general, classes ending in "Base" should not be used directly.

## Controller and Head Input

The XR browser tests provide a way to plumb controller and headset data (e.g.
currently touched/pressed buttons and poses) from the test through the runtime
being tested. Details about what goes on under the hood can be found in
[`//chrome/browser/vr/test/xr_browser_test_details.md`][xr details], but below
is a quick guide on how to use them.

[xr details]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/xr_browser_test_details.md

In order to let a test provide data to a runtime, it must create an instance of
[`MockXRDeviceHookBase`][xr hook base] or some subclass of it. This should be
created at the beginning of the test before any attempts to enter VR are made,
as there are currently assumptions that prevent switching to or from the mock
runtimes once they have been attempted to be started.

[xr hook base]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/mock_xr_device_hook_base.h

Once created, the runtime being used will call the various functions inherited
from [`VRTestHook`][vr test hook] whenever it would normally acquire or submit
data from or to an actual device. For example, `WaitGetControllerData()` will be
called every time the runtime would normally check the state of a real
controller, and `OnFrameSubmitted()` will be called each time the runtime
submits a finished frame to the headset.

[vr test hook]: https://chromium.googlesource.com/chromium/src/+/main/device/vr/test/test_hook.h

For real examples on how to use the input capabilities, look at the tests in
[`//chrome/browser/vr/webxr_vr_input_browser_test.cc`][input test].

[input test]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/webxr_vr_input_browser_test.cc