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