1# Atest Bazel Mode
2Atest is a command line tool that allows users to run Android tests locally
3without requiring knowledge of Trade Federation test harness command line
4options. It wraps the logic and calls Trade Federation under the hood. This is
5what we call Atest Standard Mode in this document.
6
7Atest Bazel Mode creates a synthetic Bazel workspace and executes tests using
8Bazel instead of calling Trade Federation directly. This mode opens up Bazel
9features such as parallelized execution, caching, and remote execution.
10Currently it is able to run all host unit tests only. Capability to run tests
11that requires a device is still work in progress.
12
13##### Table of Contents
141. [Basic Usage](#basic-usage)
152. [Advanced Usage](#advanced-usage)
163. [How It Works](#how-it-works)
174. [Difference from Atest Standard Mode](#difference-from-atest-standard-mode)
185. [Frequently Asked Questions](#faq)
19
20## <a name="basic-usage">Basic Usage</a>
21
22Atest Bazel Mode commands take the following form:
23
24>```$ atest --bazel-mode --host HelloWorldHostTest```
25<p>Note: "--host" is needed to run the test completely on the host without a device.
26
27To run multiple tests, separate test references with spaces. For example:
28
29>```$ atest --bazel-mode --host HelloWorldHostTest fastdeploy_test aapt2_tests```
30
31To run all host unit tests from the current directory:
32
33>```$ atest --bazel-mode --host --host-unit-test-only```
34
35## <a name="advanced-usage">Advanced Usage</a>
36
37Use `--bazel-arg` to forward arguments to Bazel. For example, the following
38command increases the test timeout:
39
40>```$ atest --bazel-mode --host CtsNNAPITestCases --bazel-arg=--test_timeout=600```
41
42## <a name="how-it-works">How It Works</a>
43Bazel needs a Bazel workspace to execute tests.
44In Atest Bazel Mode, we construct a synthetic workspace using module-info.json.
45The workspace contains required directory structure, symlinks and Bazel BUILD
46files to correctly invoke ```bazel test``` command. The Bazel BUILD files are
47written with customized Bazel rules. An example Build file is as follows:
48
49```
50package(default_visibility = ["//visibility:public"])
51
52load("//bazel/rules:soong_prebuilt.bzl", "soong_prebuilt")
53load("//bazel/rules:tradefed_test.bzl", "tradefed_deviceless_test")
54
55tradefed_deviceless_test(
56    name = "HelloWorldHostTest_host",
57    test = "//platform_testing/tests/example/jarhosttest:HelloWorldHostTest",
58)
59
60soong_prebuilt(
61    name = "HelloWorldHostTest",
62    module_name = "HelloWorldHostTest",
63    files = select({
64        "//bazel/rules:host": glob(["HelloWorldHostTest/host/**/*"]),
65    }),
66)
67```
68
69Atest bazel Mode will create the Bazel workspace on first run, or upon detecting
70a change to module-info.json.
71
72It will then use Bazel query to find out dependencies for the build step.
73
74In the build step, it will use Soong to build those dependencies returned by
75Bazel query.
76
77At last, ```bazel test``` command is executed for the test targets.
78
79## <a name="difference-from-atest-standard-mode">Difference from Atest Standard Mode</a>
80
81Here is a list of major differences from the Atest Standard Mode:
82* In Atest Standard Mode, user can view detailed test case result in the
83terminal, while in Bazel Mode only test target result is showing. For test case
84detail, user would need to look at test logs. The reason Bazel Mode only shows
85the summary result is that atest invokes Bazel command with default parameters.
86Bazel command option "--test_output" is defaulted to be "summary". User has the
87option to view "all" output when we later implement command option passing from
88Atest to Bazel.
89More details about Bazel [--test_output flag](https://docs.bazel.build/versions/main/command-line-reference.html#flag--test_output)
90* In Atest Standard Mode, user can identify tests by module name, class name,
91file path or package name, while in Bazel Mode, we only support module name
92currently. Supporting flexible test finder is work in progress.
93* In Atest Standard Mode, test logs are saved under ```/tmp/atest_result```, while in
94Bazel Mode, test logs are saved under ```$ANDROID_BUILD_TOP/out/atest_bazel_workspace/bazel-testlogs```
95
96
97## <a name="faq">Frequently Asked Questions</a>
98
99### 1. Why my test failed with "error: Read-only file system" in the test log?
100
101Bazel execution is done within a sandbox. The purpose is to create a hermetic
102environment for the test. This could sometimes cause issues if the test writer
103is not careful when reading and writting test data.
104
105For reading, there is not much restriction as the new Bazel sandbox design
106allows all read access to "/" since it mounted "/" as readable in the sandbox.
107
108For writting, Bazel only allows write access to the target's private execroot
109directory and a private $TMPDIR.
110
111More details about [Bazel sandbox.](https://bazel.build/designs/2016/06/02/sandboxing.html)
112
113
114### 2. Why I got "Too many levels of symbolic links" while reading files in Bazel Mode?
115
116Some tests try to read the test data using relative path. This some times does
117not work in Bazel Mode.
118
119In Bazel Mode, Bazel creates symbolic links for all the test artifacts in the
120Bazel private execution root directory in the sandbox. The symbolic links are
121eventially resolved to the physical file in Android source tree.
122Reading the symlink as file without following symlinks may fail with the above
123error message.
124
125One example is C++ android::base::ReadFileToString function. The solution is to
126enable following symbolic link when calling the function.
127More details can be find [here.](https://cs.android.com/android/platform/superproject/+/master:external/googletest/googletest/include/gtest/gtest.h;drc=master;l=2353)
128