| # Testing | |
| The testing strategy for Perfetto is rather complex due to the wide variety | |
| of build configurations and embedding targets. | |
| Common test targets (all platforms / checkouts): | |
| `perfetto_unittests`: | |
| Platform-agnostic unit-tests. | |
| `perfetto_integrationtests`: | |
| End-to-end tests, involving the protobuf-based IPC transport and ftrace | |
| integration (Linux/Android only). | |
| `perfetto_benchmarks`: | |
| Benchmarks tracking the performance of: (i) trace writing, (ii) trace readback | |
| and (iii) ftrace raw pipe -> protobuf translation. | |
| ## Running tests | |
| ### On Linux / MacOS | |
| ```bash | |
| tools/ninja -C out/default perfetto_{unittests,integrationtests,benchmarks} | |
| out/default/perfetto_unittests --gtest_help | |
| ``` | |
| `perfetto_integrationtests` requires that the ftrace debugfs directory is | |
| is readable/writable by the current user on Linux: | |
| ```bash | |
| sudo chown -R $USER /sys/kernel/debug/tracing | |
| ``` | |
| ### On Android | |
| 1. Connect a device through `adb` | |
| 2. Start the build-in emulator (supported on Linux and MacOS): | |
| ```bash | |
| tools/install-build-deps --android | |
| tools/run_android_emulator & | |
| ``` | |
| 3. Run the tests (either on the emulator or physical device): | |
| ```bash | |
| tools/run_android_test out/default perfetto_unittests | |
| ``` | |
| ## Continuous testing | |
| Perfetto is tested in a variety of locations: | |
| **Perfetto CI**: https://ci.perfetto.dev/ | |
| Builds and runs perfetto\_{unittests,integrationtests,benchmarks} from the | |
| standalone checkout. Benchmarks are ran in a reduced form for smoke testing. | |
| See [this doc](/docs/design-docs/continuous-integration.md) for more details. | |
| **Android CI** (see go/apct and go/apct-guide): | |
| runs only `perfetto_integrationtests` | |
| **Android presubmits (TreeHugger)**: | |
| Runs before submission of every AOSP CL of `external/perfetto`. | |
| **Android CTS** (Android test suite used run to ensure API compatibility): | |
| Rolling runs internally. | |
| Note that Perfetto CI uses the standalone build system and the others build as | |
| part of the Android tree. | |
| ## Unit tests | |
| Unit tests exist for most of the code in Perfetto on the class level. They | |
| ensure that each class broadly works as expected. | |
| Unit tests are currently ran on ci.perfetto.dev and build.chromium.org. | |
| Running unit tests on APCT and Treehugger is WIP. | |
| ## Integration tests | |
| Integration tests ensure that subsystems (importantly ftrace and the IPC layer) | |
| and Perfetto as a whole is working correctly end-to-end. | |
| There are two configurations in which integration tests can be run: | |
| **1. Production mode** (Android-only) | |
| This mode assumes that both the tracing service (`traced`) and the OS probes | |
| service (`traced_probes`) are already running. In this mode the test enables | |
| only the consumer endpoint and tests the interaction with the production | |
| services. This is the way our Android CTS and APCT tests work. | |
| **2. Standalone mode**: | |
| Starting up the daemons in the test itself and then testing against them. | |
| This is how standalone builds are tested. This is the only supported way to | |
| run integration tests on Linux and MacOS. | |
| ## Trace Processor diff tests | |
| Trace Processor is mainly tested using so called "diff tests" rather than | |
| unit tests. Unit tests have proven too brittle when dealing with code that | |
| parses traces — they require painful mechanical updates whenever the | |
| parsing logic is refactored — so they are reserved for the low-level | |
| building blocks the rest of Trace Processor is built on. Everything else | |
| (parsing events, table schemas, stdlib modules, dynamic tables) is covered | |
| by diff tests. | |
| For these tests, Trace Processor parses a known trace and executes a query | |
| string or file. The output of these queries is then compared (i.e. "diff"ed) | |
| against an expected output file and discrepancies are highlighted. | |
| Similar diff tests are also available when writing metrics — instead of a | |
| query, the metric name is used and the expected output string contains | |
| the expected result of computing the metric. | |
| These tests (for both queries and metrics) can be run as follows: | |
| ```bash | |
| tools/ninja -C <out directory> | |
| tools/diff_test_trace_processor.py <out directory>/trace_processor_shell | |
| ``` | |
| TIP: Query diff tests are expected to only have a single query which produces | |
| output in the whole file (usually at the end). Calling | |
| `SELECT RUN_METRIC('metric file')` can trip up this check as this query | |
| generates some hidden output. To address this issue, if a query only has | |
| column is named `suppress_query_output`, even if it has output, this will | |
| be ignored (for example, | |
| `SELECT RUN_METRIC('metric file') as suppress_query_output`) | |
| ### Adding a new diff test | |
| All diff tests live under [`test/trace_processor`](/test/trace_processor) in | |
| `tests{_category_name}.py` files as methods of a class. To add a new test, | |
| add a new method starting with `test_` in the suitable Python file. | |
| Methods cannot take arguments and have to return a `DiffTestBlueprint`: | |
| ```python | |
| class DiffTestBlueprint: | |
| trace: Union[Path, Json, Systrace, TextProto] | |
| query: Union[str, Path, Metric] | |
| out: Union[Path, Json, Csv, TextProto] | |
| ``` | |
| _Trace_ and _Out_: For every type apart from `Path`, contents of the object | |
| will be treated as file contents so it has to follow the same rules. | |
| _Query_: For metric tests it is enough to provide the metric name. For query | |
| tests there can be a raw SQL statement, for example `"SELECT * FROM SLICE"`, | |
| or a path to an `.sql` file. | |
| NOTE: `trace_processor_shell` and the associated proto descriptors need to | |
| be built before running `tools/diff_test_trace_processor.py`. The easiest | |
| way to do this is to run `tools/ninja -C <out directory>` both initially | |
| and on every change to Trace Processor code. | |
| #### Choosing where to add diff tests | |
| `diff_tests/` contains directories corresponding to different areas of | |
| Trace Processor: | |
| 1. **stdlib**: Tests focusing on the PerfettoSQL Standard Library, both the | |
| prelude and the regular modules. The subdirectories generally correspond | |
| to directories in `perfetto_sql/stdlib`. | |
| 2. **parser**: Tests focusing on ensuring different trace formats are | |
| parsed correctly and the corresponding built-in tables are populated. | |
| 3. **syntax**: Tests focusing on the core syntax of PerfettoSQL (e.g. | |
| `CREATE PERFETTO TABLE`, `CREATE PERFETTO FUNCTION`). | |
| **Scenario**: A new stdlib module `foo/bar.sql` is being added. | |
| _Answer_: Add the test to `stdlib/foo/bar_tests.py`. | |
| **Scenario**: A new event is being parsed and the focus of the test is to | |
| ensure the event is parsed correctly. | |
| _Answer_: Add the test in one of the `parser` subdirectories. Prefer | |
| adding the test to an existing related directory (e.g. `sched`, `power`) | |
| if one exists. | |
| **Scenario**: A new dynamic table is being added and the focus of the test | |
| is to ensure the dynamic table is correctly computed. | |
| _Answer_: Add the test to `stdlib/dynamic_tables`. | |
| **Scenario**: The internals of Trace Processor are being modified and the | |
| test is to ensure Trace Processor is correctly filtering/sorting important | |
| built-in tables. | |
| _Answer_: Add the test to `parser/core_tables`. | |
| ## UI pixel diff tests | |
| The pixel tests are used to ensure core user journeys work by verifying they | |
| are the same pixel to pixel against a golden screenshot. They use a headless | |
| chrome to load the webpage and take a screenshot and compare pixel by pixel a | |
| golden screenshot. You can run these tests by using `ui/run-integrationtests`. | |
| These test fail when a certain number of pixels are different. If these tests | |
| fail, you'll need to investigate the diff and determine if its intentional. If | |
| its a desired change you will need to update the screenshots on a linux machine | |
| to get the CI to pass. You can update them by generating and uploading a new | |
| baseline (this requires access to a google bucket through gcloud which only | |
| googlers have access to, googlers can install gcloud | |
| [here](https://g3doc.corp.google.com/cloud/sdk/g3doc/index.md#installing-and-using-the-cloud-sdk)). | |
| The tests are run in a docker container by default, unless -`-no-docker` is | |
| passed. It's recommended to use the container for a stable and reproducable | |
| testing environment, especially for rebaselining, otherwise it's very likely the | |
| screenshots will not match when run on the CI. | |
| ``` | |
| ui/run-integrationtests --rebaseline | |
| tools/test_data upload | |
| ``` | |
| Once finished you can commit and upload as part of your CL to cause the CI to | |
| use your new screenshots. | |
| NOTE: If you see a failing diff test you can see the pixel differences on the CI | |
| by using a link ending with `ui-test-artifacts/index.html`. Report located on | |
| that page contains changed screenshots as well as a command to accept the | |
| changes if these are desirable. | |
| ## Android CTS tests | |
| CTS tests ensure that any vendors who modify Android remain compliant with the | |
| platform API. | |
| These tests include a subset of the integration tests above as well as adding | |
| more complex tests which ensure interaction between platform (e.g. Android apps | |
| etc.) and Perfetto is not broken. | |
| The relevant targets are `CtsPerfettoProducerApp` and `CtsPerfettoTestCases`. Once these are built, the following commands should be run: | |
| ```bash | |
| adb push $ANDROID_HOST_OUT/cts/android-cts/testcases/CtsPerfettoTestCases64 /data/local/tmp/ | |
| adb install -r $ANDROID_HOST_OUT/cts/android-cts/testcases/CtsPerfettoProducerApp.apk | |
| ``` | |
| Next, the app named `android.perfetto.producer` should be run on the device. | |
| Finally, the following command should be run: | |
| ```bash | |
| adb shell /data/local/tmp/CtsPerfettoTestCases64 | |
| ``` | |
| ## {#chromium} Chromium waterfall | |
| Perfetto is constantly rolled into chromium's //third_party/perfetto via | |
| [this autoroller](https://autoroll.skia.org/r/perfetto-chromium-autoroll). | |
| The [Chromium CI](https://build.chromium.org) runs the `perfetto_unittests` | |
| target, as defined in the [buildbot config][chromium_buildbot]. | |
| You can also test a pending Perfetto CL against Chromium's CI / TryBots | |
| before submitting it. This can be useful when making trickier API changes or to | |
| test on platforms that the Perfetto CI doesn't cover (e.g. Windows, MacOS), | |
| allowing you to verify the patch before you submit it (and it then eventually | |
| auto-rolls into Chromium). | |
| To do this, first make sure you have uploaded pull request to GitHub. | |
| Next, create a new Chromium CL that modifies Chromium's | |
| `//src/DEPS` file. | |
| If you recently uploaded your change, it may be enough to modify the git commit | |
| hash in the `DEPS` entry for `src/third_party/perfetto`: | |
| ``` | |
| 'src/third_party/perfetto': | |
| Var('chromium_git') + '/external/github.com/google/perfetto/' + '@' + '8fe19f55468ee227e99c1a682bd8c0e8f7e5bcdb', | |
| ``` | |
| Replace the git hash with the commit hash of your most recent patch set. | |
| Alternatively, you can add `hooks` to patch in the pending CL on top of | |
| Chromium's current third_party/perfetto revision. For this, add the following | |
| entries to the `hooks` array in Chromium's `//src/DEPS` file, modifying the | |
| `refs/pull/XXXX/head` to the appropriate values for your pull request. | |
| ``` | |
| { | |
| 'name': 'fetch_custom_patch', | |
| 'pattern': '.', | |
| 'action': [ 'git', '-C', 'src/third_party/perfetto/', | |
| 'fetch', 'https://github.com/google/perfetto.git', | |
| 'refs/pull/XXXX/head', | |
| ], | |
| }, | |
| { | |
| 'name': 'apply_custom_patch', | |
| 'pattern': '.', | |
| 'action': ['git', '-C', 'src/third_party/perfetto/', | |
| '-c', 'user.name=Custom Patch', '-c', 'user.email=custompatch@example.com', | |
| 'cherry-pick', 'FETCH_HEAD', | |
| ], | |
| }, | |
| ``` | |
| If you'd like to test your change against the SDK build of Chrome, you | |
| can add `Cq-Include-Trybots:` lines for perfetto SDK trybots to the change | |
| description in gerrit (this won't be needed once Chrome's migration to the | |
| SDK is complete, see [tracking bug][sdk_migration_bug]): | |
| ``` | |
| Cq-Include-Trybots: luci.chromium.try:linux-perfetto-rel | |
| Cq-Include-Trybots: luci.chromium.try:android-perfetto-rel | |
| Cq-Include-Trybots: luci.chromium.try:mac-perfetto-rel | |
| Cq-Include-Trybots: luci.chromium.try:win-perfetto-rel | |
| ``` | |
| [chromium_buildbot]: https://cs.chromium.org/search/?q=perfetto_.*tests+f:%5Esrc/testing.*json$&sq=package:chromium&type=cs | |
| [chromium_cl]: https://chromium-review.googlesource.com/c/chromium/src/+/2030528 | |
| [sdk_migration_bug]: https://crbug.com/1006541 |