Chromium Code Reviews| Index: testing/android/docs/gtest_implementation.md |
| diff --git a/testing/android/docs/gtest_implementation.md b/testing/android/docs/gtest_implementation.md |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..dd67653eaf655cdea7b953e4d1699a954c73ec0d |
| --- /dev/null |
| +++ b/testing/android/docs/gtest_implementation.md |
| @@ -0,0 +1,132 @@ |
| +# How GTests work on Android |
| + |
| +gtests are [googletest](https://github.com/google/googletest)-based C++ tests. |
| +On Android, they run on a device. In most cases, they're packaged as APKs, but |
| +there are a few cases where they're run as raw executables. The latter is |
| +necessary in a few cases, particularly when manipulating signal handlers, but |
| +isn't possible when the suite needs to call back through the JNI into Java code. |
| + |
| +[TOC] |
| + |
| +## APKs |
| + |
| +### GN |
| + |
| +Gtest APKs are built by default by the |
| +[test](https://codesearch.chromium.org/chromium/src/testing/test.gni?type=cs&q=file:%5Esrc%5C/testing%5C/test.gni$+template%5C("test"%5C)&sq=package:chromium) |
| +template, e.g. |
| + |
| +```python |
| +test("sample_gtest") { |
| + # ... |
| +} |
| +``` |
| + |
| +This uses gn's native |
| +[shared_library](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/reference.md#shared_library_Declare-a-shared-library-target) |
| +target type along with the |
| +[unittest_apk](https://codesearch.chromium.org/chromium/src/build/config/android/rules.gni?type=cs&q=file:%5Esrc%5C/build%5C/config%5C/android%5C/rules.gni$+template%5C(%5C"unittest_apk%5C"%5C)&sq=package:chromium) |
| +template to build an APK containing: |
| + |
| + - One or more .so files containing the native code on which the test suite |
| +depends |
| + - One or more .dex files containing the Java code on which the test suite |
| +depends |
| + - A [manifest](https://developer.android.com/guide/topics/manifest/manifest-intro.html) |
| +file that contains `<instrumentation>` and `<activity>` elements (among others). |
| + |
| +### Harness |
| + |
| +GTest APKs are packaged with a harness that consists of: |
| + |
| + - [NativeTestInstrumentationTestRunner], an instrumentation entry point that |
| +handles running one or more sequential instances of a test Activity. Typically, |
| +unit test suites will only use one instance of the Activity and will run all of |
| +the specified tests in it, while browser test suites will use multiple instances |
| +and will only run one test per instance. |
| + - Three [Activity](https://developer.android.com/reference/android/app/Activity.html)-based |
| +classes |
| +([NativeUnitTestActivity](https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestActivity.java), |
| +[NativeUnitTestNativeActivity](https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTestNativeActivity.java), |
| +and |
| +[NativeBrowserTestActivity](https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeBrowserTestActivity.java)) |
| +that primarily act as process entry points for individual test shards. |
| +Only one is used in any given suite. |
| + - [NativeTest] and [NativeUnitTest], |
| +which handle formatting arguments for googletest and transferring control across |
| +the JNI. |
| + - [testing::android::RunTests](https://codesearch.chromium.org/chromium/src/testing/android/native_test/native_test_launcher.cc?q=file:%5Esrc%5C/testing%5C/android%5C/native_test%5C/native_test_launcher.cc$+RunTests&sq=package:chromium), |
| +the function on the native side, which initializes the native command-line, |
| +redirects stdout either to a FIFO or a regular file, optionally waits for a |
| +debugger to attach to the process, sets up the test data directories, and then |
| +dispatches to googletest's `main` function. |
| + |
| +### Runtime |
| + |
| + 1. The test runner calls `am instrument` with a bunch of arguments, |
| + includes several extras that are arguments to either |
| + [NativeTestInstrumentationTestRunner] or [NativeTest]. This results in an |
| + intent being sent to [NativeTestInstrumentationTestRunner]. |
| + 2. [NativeTestInstrumentationTestRunner] is created. In its onCreate, it |
| + parses its own arguments from the intent and retains all other arguments |
| + to be passed to the Activities it'll start later. It also creates a |
| + temporary file in the external storage directory for stdout. It finally |
| + starts itself. |
| + 3. [NativeTestInstrumentationTestRunner] is started. In its onStart, it prepares |
| + to receive notifications about the start and end of the test run from the |
| + Activities it's about to start. It then creates [ShardStarter] |
| + that will start the first test shard and adds that to the current |
| + [Handler](https://developer.android.com/reference/android/os/Handler.html). |
| + 4. The [ShardStarter] is executed, starting the test Activity. |
| + 5. The Activity starts, possibly doing some process initialization, and hands |
| + off to the [NativeTest]. |
| + 6. The [NativeTest] handles some initialization and informs the |
| + [NativeTestInstrumentationTestRunner] that it has started. On hearing this, |
| + the [NativeTestInstrumentationTestRunner] creates a [ShardMonitor] |
| + that will monitor the execution of the test Activity. |
| + 7. The [NativeTest] hands off to testing::android::RunTests. The tests run. |
| + 8. The [NativeTest] informs the [NativeTestInstrumentationTestRunner] that is has |
| + completed. On hearing this, the [ShardMonitor] creates a [ShardEnder]. |
| + 9. The [ShardEnder] is executed, killing the child process (if applicable), |
| + parsing the results from the stdout file, and either launching the next |
| + shard via [ShardStarter] (in which case the process returns to #4) or sending |
| + the results out to the test runner and finishing the instrumentation. |
| + |
| +## Executables |
| + |
| +### GN |
| + |
| +Gtest executables are built by passing |
| +`use_raw_android_executable = True` to the |
| +[test](https://codesearch.chromium.org/chromium/src/testing/test.gni?type=cs&q=file:%5Esrc%5C/testing%5C/test.gni$+template%5C("test"%5C)&sq=package:chromium) |
| +template, e.g. |
| + |
| +```python |
| +test("sample_gtest_executable") { |
| + if (is_android) { |
| + use_raw_android_executable = true |
| + } |
| + # ... |
| +} |
| +``` |
| + |
| +This uses gn's native |
| +[executable](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/reference.md#executable_Declare-an-executable-target) |
| +target type, then copies the resulting executable and any requisite shared libraries |
| +to ```${root_out_dir}/${target_name}__dist``` (e.g. ```out/Debug/breakpad_unittests__dist```). |
| + |
| +### Harness |
| + |
| +Unlike APKs, gtest suites built as executables require no Android-specific harnesses. |
| + |
| +### Runtime |
| + |
| +The test runner simply executes the binary directly and parses the stdout on |
|
mikecase (-- gone --)
2016/09/07 18:55:23
question (kinda for me). Is the binary executed on
jbudorick
2016/09/08 00:32:56
On the device. Clarified here.
|
| +its own. |
| + |
| +[NativeTest]: https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeTest.java |
| +[NativeTestInstrumentationTestRunner]: https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java |
| +[NativeUnitTest]: https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeUnitTest.java |
| +[ShardEnder]: https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java?q=file:NativeTestInstrumentationTestRunner.java+class:ShardEnder&sq=package:chromium |
| +[ShardMonitor]: https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java?q=file:NativeTestInstrumentationTestRunner.java+class:ShardMonitor&sq=package:chromium |
| +[ShardStarter]: https://codesearch.chromium.org/chromium/src/testing/android/native_test/java/src/org/chromium/native_test/NativeTestInstrumentationTestRunner.java?q=file:NativeTestInstrumentationTestRunner.java+class:ShardStarter&sq=package:chromium |