From af1ffa2addc7bf7711ca2fcd6fde727496bafe81 Mon Sep 17 00:00:00 2001 From: Igor Sarkisov Date: Wed, 18 Dec 2024 21:59:46 -0800 Subject: [PATCH 01/14] Chrobalt on-device test work for Android b/354062546 --- .github/actions/on_device_tests/action.yaml | 156 +++++++++++++++++++- .github/config/android-arm.json | 2 + .github/workflows/main.yaml | 35 ++++- 3 files changed, 187 insertions(+), 6 deletions(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index df6b4bf39d626..2d8b8c42a02f7 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -1,9 +1,157 @@ -name: On Host Tests -description: Runs on-host tests. +name: On Device Test +description: Runs on-device tests. + runs: using: "composite" steps: - - name: Run On-Device Tests + - name: Install Requirements + run: | + pip3 install grpcio==1.38.0 grpcio-tools==1.38.0 + shell: bash + - name: Generate gRPC files + run: | + python -m grpc_tools.protoc -Itools/ --python_out=tools/ --grpc_python_out=tools/ tools/on_device_tests_gateway.proto + shell: bash + - name: Set Up Cloud SDK + uses: isarkis/setup-gcloud@40dce7857b354839efac498d3632050f568090b6 # v1.1.1 + - name: Set env vars + run: | + echo "PROJECT_NAME=$(gcloud config get-value project)" >> $GITHUB_ENV + + # Test results and logs + echo "GCS_RESULTS_PATH=gs://cobalt-unittest-storage/results/${{ matrix.name }}/${{ github.run_id }}" >> $GITHUB_ENV + + # Dimension env + if [ "${{ matrix.dimension }}" != "null" ]; then + echo "DIMENSION=${{ matrix.dimension }}" >> $GITHUB_ENV + fi + + echo "TEST_TYPE=unit_test" >> $GITHUB_ENV shell: bash + - name: Run ${{ env.SHARD_NAME }} Tests on ${{ matrix.platform }} Platform + env: + GCS_PATH: gs://${{ env.PROJECT_NAME }}-test-artifacts/${{ github.workflow }}/${{ github.run_number }}/${{ matrix.platform }}_${{ matrix.config }} + GITHUB_SHA: ${{ github.sha }} + GITHUB_TOKEN: ${{ github.token }} + GITHUB_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }} + GITHUB_ACTOR_ID: ${{ github.actor_id }} + GITHUB_REPO: ${{ github.repository }} + GITHUB_PR_HEAD_USER_LOGIN: ${{ github.event.pull_request.head.user.login }} + GITHUB_PR_HEAD_USER_ID: ${{ github.event.pull_request.head.user.id }} + GITHUB_COMMIT_AUTHOR_USERNAME: ${{ github.event.commits[0].author.username }} + GITHUB_COMMIT_AUTHOR_EMAIL: ${{ github.event.commits[0].author.email }} + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} + GITHUB_RUN_NUMBER: ${{ github.run_number }} + GITHUB_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GITHUB_WORKFLOW: ${{ github.workflow }} run: | - echo "Nothing yet" + set -uxe + python3 -u tools/on_device_tests_gateway_client.py \ + --github_workspace ${GITHUB_WORKSPACE} \ + --token ${GITHUB_TOKEN} \ + --change_id ${GITHUB_PR_NUMBER:-postsubmit} \ + trigger \ + --test_type ${TEST_TYPE} \ + --platform ${{ matrix.target_platform }} \ + --config ${{ matrix.config }} \ + --tag cobalt_github_${GITHUB_EVENT_NAME} \ + --builder_name github_${{ matrix.platform }}_tests \ + --build_number ${GITHUB_RUN_NUMBER} \ + --builder_url ${GITHUB_RUN_URL} \ + ${LOADER_PLATFORM:+"--loader_config" "$LOADER_CONFIG"} \ + ${LOADER_PLATFORM:+"--loader_platform" "$LOADER_PLATFORM"} \ + ${DIMENSION:+"--dimension" "$DIMENSION"} \ + ${USE_SHARDING:+"--unittest_shard_index" "${{ matrix.shard }}"} \ + ${ON_DEVICE_TEST_ATTEMPTS:+"--test_attempts" "$ON_DEVICE_TEST_ATTEMPTS"} \ + --archive_path "${GCS_PATH}/artifacts.tar" \ + --gcs_result_path "${GCS_RESULTS_PATH}" \ + --label github \ + --label ${GITHUB_EVENT_NAME} \ + --label ${GITHUB_WORKFLOW} \ + --label actor-${GITHUB_ACTOR} \ + --label actor_id-${GITHUB_ACTOR_ID} \ + --label triggering_actor-${GITHUB_TRIGGERING_ACTOR} \ + --label sha-${GITHUB_SHA} \ + --label repository-${GITHUB_REPO} \ + --label author-${GITHUB_PR_HEAD_USER_LOGIN:-$GITHUB_COMMIT_AUTHOR_USERNAME} \ + --label author_id-${GITHUB_PR_HEAD_USER_ID:-$GITHUB_COMMIT_AUTHOR_EMAIL} + shell: bash + - name: Download ${{ matrix.platform }} Test Results + if: always() && env.TEST_TYPE == 'unit_test' + run: | + # Don't break on error (-e), some commands are expected to fail. + set -ux + + COBALT_LOGS_DIR="${GITHUB_WORKSPACE}/cobalt_logs" + UNIT_TEST_RESULT_PATH="${GITHUB_WORKSPACE}/unit-test-results" + COBALT_XMLS_FILENAME="cobalt_xmls.zip" + + # Forward environment variables for uploading artifacts in later steps. + echo "UNIT_TEST_RESULT_PATH=${UNIT_TEST_RESULT_PATH}" >> $GITHUB_ENV + echo "COBALT_LOGS_DIR=${COBALT_LOGS_DIR}" >> $GITHUB_ENV + + mkdir -p "${GITHUB_WORKSPACE}/test_results" + cd "${GITHUB_WORKSPACE}/test_results" + + i=0 + # Try downloading the results for 6x 10 seconds before giving up. + while [ $i -lt 6 ]; do + # The results are uploaded after the test has completed. + sleep 10 + + # The log files are named by the device lab test driver. + COBALT_ERROR_LOG_FILENAME="webDriverTestLog.ERROR" + COBALT_INFO_LOG_FILENAME="webDriverTestLog.INFO" + + # This command will fail until the results have been uploaded. + gsutil cp "${GCS_RESULTS_PATH}/${COBALT_ERROR_LOG_FILENAME}" . + gsutil cp "${GCS_RESULTS_PATH}/${COBALT_INFO_LOG_FILENAME}" . + gsutil cp "${GCS_RESULTS_PATH}/${COBALT_XMLS_FILENAME}" . + + # Break if all files were downloaded. + if [[ -f "${COBALT_XMLS_FILENAME}" && -f "${COBALT_ERROR_LOG_FILENAME}" && -f "${COBALT_INFO_LOG_FILENAME}" ]]; then + break + fi + + i=$(( ${i} + 1 )) + done + + # Rename log files for archiving to not expose legacy weirdness. + mkdir -p "${COBALT_LOGS_DIR}/${{ matrix.platform }}/" + cp "${COBALT_ERROR_LOG_FILENAME}" "${COBALT_LOGS_DIR}/${{ matrix.platform }}/stderr_${{ matrix.shard }}.log" + cp "${COBALT_INFO_LOG_FILENAME}" "${COBALT_LOGS_DIR}/${{ matrix.platform }}/stdout_${{ matrix.shard }}.log" + + # Prepare unit test results for DataDog upload. + RESULT_PATH=${UNIT_TEST_RESULT_PATH}/${{ matrix.platform }}/${{ matrix.shard }}/ + mkdir -p ${RESULT_PATH} + + # Set tags for test differentiation. + tags="os.platform:${{ matrix.platform }}" + echo $tags > ${UNIT_TEST_RESULT_PATH}/${{ matrix.platform }}/TAGS + + unzip ${COBALT_XMLS_FILENAME} -d ${RESULT_PATH} + shell: bash + - name: Archive Unit Test Logs + uses: actions/upload-artifact@v3 + if: always() && env.TEST_TYPE == 'unit_test' + with: + name: Device logs + path: ${{ env.COBALT_LOGS_DIR }}/ + - name: Archive Unit Test Results + uses: actions/upload-artifact@v3 + if: always() && env.TEST_TYPE == 'unit_test' + with: + name: unit-test-results + path: ${{ env.UNIT_TEST_RESULT_PATH }}/ + - name: Print device logs + if: always() + run: | + if ls ${COBALT_LOGS_DIR}/**/*.log 1> /dev/null 2>&1; then + cat ${COBALT_LOGS_DIR}/**/*.log + else + echo "No device logs found" + fi + shell: bash diff --git a/.github/config/android-arm.json b/.github/config/android-arm.json index e8be887ccd2aa..684725c6f75e2 100644 --- a/.github/config/android-arm.json +++ b/.github/config/android-arm.json @@ -21,6 +21,8 @@ "sql_unittests", "url_unittests" ], + "gtest_device": "sabrina", + "gtest_lab": "maneki", "test_on_device": true, "includes": [ { diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 15405744faa1a..43c2ccb2aa8ee 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -182,9 +182,9 @@ jobs: on_host: ${{ needs.initialize.outputs.test_on_host }} on_device: ${{ needs.initialize.outputs.test_on_device }} - test: + on-host-test: needs: [initialize, docker-build-image, build] - if: needs.initialize.outputs.test_on_host == 'true' || needs.initialize.outputs.test_on_device == 'true' + if: needs.initialize.outputs.test_on_host == 'true' permissions: {} # TODO(b/372303096): Should have dedicated runner? runs-on: [self-hosted, chrobalt-linux-runner] @@ -224,3 +224,34 @@ jobs: test_results_key: ${{ env.TEST_RESULTS_KEY }} datadog_api_key: ${{ secrets.datadog_api_key }} continue-on-error: true + + # Runs on-device integration and unit tests. + on-device-test: + needs: [initialize, build] + # Run ODT when on_device label is applied on PR. + # Also, run ODT on push and schedule if not explicitly disabled via repo vars. + if: | + needs.initialize.outputs.test_on_device == 'true' && (( + github.event_name == 'pull_request' && + contains(github.event.pull_request.labels.*.name, 'on_device') ) || (( + inputs.nightly == 'true' || github.event_name == 'schedule') && + vars.RUN_ODT_TESTS_ON_NIGHTLY != 'False') || + ( github.event_name == 'push' && vars.RUN_ODT_TESTS_ON_POSTSUBMIT != 'False' ) ) + runs-on: [self-hosted, odt-runner] + name: ${{ matrix.name }}_on_device + permissions: {} + strategy: + fail-fast: false + matrix: + platform: ${{ fromJson(needs.initialize.outputs.platforms) }} + config: [devel] + include: ${{ fromJson(needs.initialize.outputs.includes) }} + steps: + - name: Checkout + uses: kaidokert/checkout@v3.5.999 + timeout-minutes: 30 + with: + fetch-depth: 1 + persist-credentials: false + - name: Run Tests (${{ matrix.shard }}) + uses: ./.github/actions/on_device_tests From 0923ffc2a7615f09c3eca71bb583ef4bec510bcd Mon Sep 17 00:00:00 2001 From: Igor Sarkisov Date: Thu, 19 Dec 2024 14:30:59 -0800 Subject: [PATCH 02/14] Update params passed to ODT gateway --- .github/actions/on_device_tests/action.yaml | 44 ++------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index 2d8b8c42a02f7..b03c0772535c8 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -25,59 +25,21 @@ runs: if [ "${{ matrix.dimension }}" != "null" ]; then echo "DIMENSION=${{ matrix.dimension }}" >> $GITHUB_ENV fi - - echo "TEST_TYPE=unit_test" >> $GITHUB_ENV shell: bash - name: Run ${{ env.SHARD_NAME }} Tests on ${{ matrix.platform }} Platform env: GCS_PATH: gs://${{ env.PROJECT_NAME }}-test-artifacts/${{ github.workflow }}/${{ github.run_number }}/${{ matrix.platform }}_${{ matrix.config }} - GITHUB_SHA: ${{ github.sha }} - GITHUB_TOKEN: ${{ github.token }} - GITHUB_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} - GITHUB_EVENT_NAME: ${{ github.event_name }} - GITHUB_ACTOR: ${{ github.actor }} - GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }} - GITHUB_ACTOR_ID: ${{ github.actor_id }} - GITHUB_REPO: ${{ github.repository }} - GITHUB_PR_HEAD_USER_LOGIN: ${{ github.event.pull_request.head.user.login }} - GITHUB_PR_HEAD_USER_ID: ${{ github.event.pull_request.head.user.id }} - GITHUB_COMMIT_AUTHOR_USERNAME: ${{ github.event.commits[0].author.username }} - GITHUB_COMMIT_AUTHOR_EMAIL: ${{ github.event.commits[0].author.email }} - GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} - GITHUB_RUN_NUMBER: ${{ github.run_number }} - GITHUB_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} - GITHUB_WORKFLOW: ${{ github.workflow }} run: | set -uxe python3 -u tools/on_device_tests_gateway_client.py \ - --github_workspace ${GITHUB_WORKSPACE} \ + --platform_json "${GITHUB_WORKSPACE}/src/.github/config/${{ matrix.platform}}.json" \ + --filter_json_dir "${GITHUB_WORKSPACE}/src/cobalt/testing/${{ matrix.platform}}" \ --token ${GITHUB_TOKEN} \ - --change_id ${GITHUB_PR_NUMBER:-postsubmit} \ - trigger \ - --test_type ${TEST_TYPE} \ - --platform ${{ matrix.target_platform }} \ - --config ${{ matrix.config }} \ - --tag cobalt_github_${GITHUB_EVENT_NAME} \ - --builder_name github_${{ matrix.platform }}_tests \ - --build_number ${GITHUB_RUN_NUMBER} \ - --builder_url ${GITHUB_RUN_URL} \ - ${LOADER_PLATFORM:+"--loader_config" "$LOADER_CONFIG"} \ - ${LOADER_PLATFORM:+"--loader_platform" "$LOADER_PLATFORM"} \ ${DIMENSION:+"--dimension" "$DIMENSION"} \ - ${USE_SHARDING:+"--unittest_shard_index" "${{ matrix.shard }}"} \ ${ON_DEVICE_TEST_ATTEMPTS:+"--test_attempts" "$ON_DEVICE_TEST_ATTEMPTS"} \ --archive_path "${GCS_PATH}/artifacts.tar" \ --gcs_result_path "${GCS_RESULTS_PATH}" \ - --label github \ - --label ${GITHUB_EVENT_NAME} \ - --label ${GITHUB_WORKFLOW} \ - --label actor-${GITHUB_ACTOR} \ - --label actor_id-${GITHUB_ACTOR_ID} \ - --label triggering_actor-${GITHUB_TRIGGERING_ACTOR} \ - --label sha-${GITHUB_SHA} \ - --label repository-${GITHUB_REPO} \ - --label author-${GITHUB_PR_HEAD_USER_LOGIN:-$GITHUB_COMMIT_AUTHOR_USERNAME} \ - --label author_id-${GITHUB_PR_HEAD_USER_ID:-$GITHUB_COMMIT_AUTHOR_EMAIL} + trigger \ shell: bash - name: Download ${{ matrix.platform }} Test Results if: always() && env.TEST_TYPE == 'unit_test' From ffd6059258b867c385d39a94346c893665cd6612 Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Fri, 20 Dec 2024 23:36:40 +0000 Subject: [PATCH 03/14] ODT Client code --- .../android-arm/base_unittests_filter.json | 10 + tools/on_device_tests_gateway.proto | 81 ++++ tools/on_device_tests_gateway_client.py | 305 ++++++++++++ tools/on_device_tests_gateway_pb2.py | 437 ++++++++++++++++++ tools/on_device_tests_gateway_pb2_grpc.py | 64 +++ 5 files changed, 897 insertions(+) create mode 100644 cobalt/testing/android-arm/base_unittests_filter.json create mode 100644 tools/on_device_tests_gateway.proto create mode 100644 tools/on_device_tests_gateway_client.py create mode 100644 tools/on_device_tests_gateway_pb2.py create mode 100644 tools/on_device_tests_gateway_pb2_grpc.py diff --git a/cobalt/testing/android-arm/base_unittests_filter.json b/cobalt/testing/android-arm/base_unittests_filter.json new file mode 100644 index 0000000000000..bb161c725dc43 --- /dev/null +++ b/cobalt/testing/android-arm/base_unittests_filter.json @@ -0,0 +1,10 @@ +{ + "failing_tests": [ + "BreakIteratorTest.BreakCharacter", + "ValuesUtilTest.FilePath" + ], + "passing_tests": [ + "test1", + "test2" + ] +} diff --git a/tools/on_device_tests_gateway.proto b/tools/on_device_tests_gateway.proto new file mode 100644 index 0000000000000..50cc02d478f7e --- /dev/null +++ b/tools/on_device_tests_gateway.proto @@ -0,0 +1,81 @@ +// Copyright 2022 The Cobalt Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package on_device_tests_gateway; + +// Interface exported by the server. +service on_device_tests_gateway { + // A dumb proxy RPC service that passes user defined command line options + // to the on-device tests gateway and streams back output in real time. + rpc exec_command (OnDeviceTestsCommand) returns (stream OnDeviceTestsResponse) { + } + + rpc exec_watch_command (OnDeviceTestsWatchCommand) returns (stream OnDeviceTestsResponse) { + } +} + +// Working directory and command line arguments to be passed to the gateway. +message OnDeviceTestsCommand { + // Next ID: 23 + string workdir = 1; + string token = 2; + string test_type = 3; + string platform = 4; + string archive_path = 5; + string config = 6; + string tag = 7; + repeated string labels = 8; + string builder_name = 9; + string change_id = 10; + string build_number = 11; + string loader_platform = 12; + string loader_config = 13; + string version = 14; + bool dry_run = 15; + repeated string dimension = 16; + string unittest_shard_index = 17; + string test_attempts = 18; + string retry_level = 19; + string start_timeout = 20; + string test_timeout = 21; + string builder_url = 22; + string gcs_result_path = 23; + repeated ApkTest apk_tests = 24; +} + +message ApkTest { + string test_target = 1; + string apk_path = 2; + string device_model = 3; + string device_pool = 4; + string gtest_filters = 5; +} + +// Working directory and command line arguments to be passed to the gateway. +message OnDeviceTestsWatchCommand { + // Next ID: 6 + string workdir = 1; + string token = 2; + string session_id = 3; + string change_id = 4; + bool dry_run = 5; +} + +// Response from the on-device tests. +message OnDeviceTestsResponse { + // Next ID: 2 + string response = 1; +} diff --git a/tools/on_device_tests_gateway_client.py b/tools/on_device_tests_gateway_client.py new file mode 100644 index 0000000000000..99cdbb5f7166a --- /dev/null +++ b/tools/on_device_tests_gateway_client.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python3 +# +# Copyright 2022 The Cobalt Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""gRPC On-device Tests Gateway client.""" + +import argparse +import logging +import sys +import os +import json + +import grpc + +import on_device_tests_gateway_pb2 +import on_device_tests_gateway_pb2_grpc + +# All tests On-Device tests support +_TEST_TYPES = [ + 'black_box_test', + 'evergreen_test', + 'unit_test', +] + +# All test configs On-Device tests support +_TEST_CONFIGS = [ + 'devel', + 'staging', + 'production', +] + +_WORK_DIR = '/on_device_tests_gateway' +_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ( + #'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') + 'localhost') +#_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' +_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '12345' + + +class OnDeviceTestsGatewayClient(): + """On-device tests Gateway Client class.""" + + def __init__(self): + self.channel = grpc.insecure_channel( + target=f'{_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST}:{_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT}', # pylint:disable=line-too-long + # These options need to match server settings. + options=[('grpc.keepalive_time_ms', 10000), + ('grpc.keepalive_timeout_ms', 5000), + ('grpc.keepalive_permit_without_calls', 1), + ('grpc.http2.max_pings_without_data', 0), + ('grpc.http2.min_time_between_pings_ms', 10000), + ('grpc.http2.min_ping_interval_without_data_ms', 5000)]) + self.stub = on_device_tests_gateway_pb2_grpc.on_device_tests_gatewayStub( + self.channel) + + def run_trigger_command(self, workdir: str, args: argparse.Namespace, apk_tests = None): + """Calls On-Device Tests service and passing given parameters to it. + + Args: + workdir (str): Current script workdir. + args (Namespace): Arguments passed in command line. + """ + for response_line in self.stub.exec_command( + on_device_tests_gateway_pb2.OnDeviceTestsCommand( + workdir=workdir, + token=args.token, + #test_type=args.test_type, + platform=args.platform, + archive_path=args.archive_path, + #config=args.config, + #tag=args.tag, + labels=args.label, + gcs_result_path=args.gcs_result_path, + #builder_name=args.builder_name, + #builder_url=args.builder_url, + change_id=args.change_id, + #build_number=args.build_number, + #loader_platform=args.loader_platform, + #loader_config=args.loader_config, + #version=args.version, + dry_run=args.dry_run, + dimension=args.dimension or [], + #unittest_shard_index=args.unittest_shard_index, + test_attempts=args.test_attempts, + retry_level=args.retry_level, + apk_tests=apk_tests, + )): + + print(response_line.response) + + def run_watch_command(self, workdir: str, args: argparse.Namespace): + """Calls On-Device Tests watch service and passing given parameters to it. + + Args: + workdir (str): Current script workdir. + args (Namespace): Arguments passed in command line. + """ + for response_line in self.stub.exec_watch_command( + on_device_tests_gateway_pb2.OnDeviceTestsWatchCommand( + workdir=workdir, + token=args.token, + change_id=args.change_id, + session_id=args.session_id, + )): + + print(response_line.response) + +def _read_json_config(filename): + """ + Reads and parses data from a JSON configuration file. + + Args: + filename: The name of the JSON configuration file. + + Returns: + A list of dictionaries, where each dictionary represents a test configuration. + """ + try: + with open(filename, 'r') as f: + data = json.load(f) + return data + except FileNotFoundError: + #print(f" Config file '{filename}' not found.") + return None + except json.JSONDecodeError: + #print(f" Invalid JSON format in '{filename}'.") + return None + +def _default_platform_json_file(platform): + current_dir = os.path.dirname(os.path.abspath(__file__)) + relative_path = os.path.join("..", ".github", "config", platform + ".json") + return os.path.join(current_dir, relative_path) + +def _get_tests_filter_json_file(platform, gtest_target): + current_dir = os.path.dirname(os.path.abspath(__file__)) + relative_path = os.path.join("..", "cobalt", "testing", platform, gtest_target + "_filter.json") + return os.path.join(current_dir, relative_path) + +def _process_apk_tests(args): + apk_tests = [] + platform_json_file = args.platform_json if args.platform_json else _default_platform_json_file(args.platform) + #print(' The platform_json_file is ' + platform_json_file) + platform_json_file_data = _read_json_config(platform_json_file) + gtest_device = platform_json_file_data["gtest_device"] + gtest_lab = platform_json_file_data["gtest_lab"] + gtest_blaze_target = "//experimental/cobalt/chrobalt_poc:custom_chrobalt_unit_tests_" + gtest_device + default_gtest_filters = "GURL*" + + #print(' processing gtest_targets in json file') + for gtest_target in platform_json_file_data["gtest_targets"]: + apk_test = { + "test_target": gtest_blaze_target, + "device_model": gtest_device, + "device_pool": gtest_lab + } + print(f" gtest_target: {gtest_target}") + gtest_filter_json_file = _get_tests_filter_json_file(args.platform, gtest_target) + print(f" gtest_filter_json_file = {gtest_filter_json_file}") + gtest_filter_json_file_data = _read_json_config(gtest_filter_json_file) + gtest_filters = default_gtest_filters + if gtest_filter_json_file_data is None: + print(" This gtest_target does not have gtest_filters_specified"); + else: + failing_tests_list = gtest_filter_json_file_data["failing_tests"] + passing_tests_list = gtest_filter_json_file_data["passing_tests"] + #print(f" failing tests in json: {failing_tests_list}") + #print(f" passing tests in json: {passing_tests_list}") + failing_tests_string = ":".join(failing_tests_list) + passing_tests_string = ":".join(passing_tests_list) + #print(f" failing_tests_string = '{failing_tests_string}'") + #print(f" passing_tests_string = '{passing_tests_string}'") + if passing_tests_string: + gtest_filters += ":" + passing_tests_string + if failing_tests_string: + gtest_filters += ":-" + failing_tests_string + #print(f" gtest_filters = {gtest_filters}"); + apk_test["apk_path"] = "/bigstore/yt-temp/" + gtest_target + "-debug.apk" + apk_test["gtest_filters"] = gtest_filters + apk_tests.append(apk_test) + + print(f" apk_tests: {apk_tests}") + return apk_tests + +def main(): + """Main routine.""" + print('Starting main routine') + + logging.basicConfig( + level=logging.INFO, format='[%(filename)s:%(lineno)s] %(message)s') + + parser = argparse.ArgumentParser( + epilog=('Example: ./on_device_tests_gateway_client.py ' + '--test_type=unit_test ' + '--remote_archive_path=gs://my_bucket/path/to/artifacts.tar ' + '--platform=raspi-2 ' + '--config=devel'), + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument( + '-t', + '--token', + type=str, + required=True, + help='On Device Tests authentication token') + parser.add_argument( + '--dry_run', + action='store_true', + help='Specifies to show what would be done without actually doing it.') + parser.add_argument( + '-i', + '--change_id', + type=str, + help='ChangeId that triggered this test, if any. ' + 'Saved with performance test results.') + + subparsers = parser.add_subparsers( + dest='action', help='On-Device tests commands', required=True) + trigger_parser = subparsers.add_parser( + 'trigger', help='Trigger On-Device tests') + + trigger_parser.add_argument( + '-p', + '--platform', + type=str, + required=True, + help='Platform this test was built for.') + trigger_parser.add_argument( + '-pf', + '--platform_json', + type=str, + help='Platform-specific json file containing the list of target tests.') + trigger_parser.add_argument( + '-a', + '--archive_path', + type=str, + required=True, + help='Path to Chrobalt archive to be tested. Must be on gcs.') + trigger_parser.add_argument( + '-l', + '--label', + type=str, + default=[], + action='append', + help='Additional labels to assign to the test.') + trigger_parser.add_argument( + '--gcs_result_path', + type=str, + help='GCS url where test result files should be uploaded.') + trigger_parser.add_argument( + '--dimension', + type=str, + action='append', + help='On-Device Tests dimension used to select a device. ' + 'Must have the following form: =.' + ' E.G. "release_version=regex:10.*') + trigger_parser.add_argument( + '--test_attempts', + type=str, + default='1', + required=False, + help='The maximum number of times a test could retry.') + trigger_parser.add_argument( + '--retry_level', + type=str, + default='ERROR', + required=False, + help='The retry level of Mobile harness job. Either ERROR (to retry for ' + 'MH errors) or FAIL (to retry for failing tests). Setting retry_level to ' + 'FAIL will also retry for MH errors.') + + watch_parser = subparsers.add_parser('watch', help='Trigger On-Device tests') + watch_parser.add_argument( + 'session_id', + type=str, + help='Session id of a previously triggered mobile ' + 'harness test. If passed, the test will not be ' + 'triggered, but will be watched until the exit ' + 'status is reached.') + + args = parser.parse_args() + apk_tests = _process_apk_tests(args) + + client = OnDeviceTestsGatewayClient() + try: + if args.action == 'trigger': + client.run_trigger_command(workdir=_WORK_DIR, args=args, apk_tests=apk_tests) + else: + client.run_watch_command(workdir=_WORK_DIR, args=args) + except grpc.RpcError as e: + print(e) + return e.code().value + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/on_device_tests_gateway_pb2.py b/tools/on_device_tests_gateway_pb2.py new file mode 100644 index 0000000000000..f6c8947b850fa --- /dev/null +++ b/tools/on_device_tests_gateway_pb2.py @@ -0,0 +1,437 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: on_device_tests_gateway.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='on_device_tests_gateway.proto', + package='on_device_tests_gateway', + syntax='proto3', + serialized_pb=_b('\n\x1don_device_tests_gateway.proto\x12\x17on_device_tests_gateway\"\x9c\x04\n\x14OnDeviceTestsCommand\x12\x0f\n\x07workdir\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x11\n\ttest_type\x18\x03 \x01(\t\x12\x10\n\x08platform\x18\x04 \x01(\t\x12\x14\n\x0c\x61rchive_path\x18\x05 \x01(\t\x12\x0e\n\x06\x63onfig\x18\x06 \x01(\t\x12\x0b\n\x03tag\x18\x07 \x01(\t\x12\x0e\n\x06labels\x18\x08 \x03(\t\x12\x14\n\x0c\x62uilder_name\x18\t \x01(\t\x12\x11\n\tchange_id\x18\n \x01(\t\x12\x14\n\x0c\x62uild_number\x18\x0b \x01(\t\x12\x17\n\x0floader_platform\x18\x0c \x01(\t\x12\x15\n\rloader_config\x18\r \x01(\t\x12\x0f\n\x07version\x18\x0e \x01(\t\x12\x0f\n\x07\x64ry_run\x18\x0f \x01(\x08\x12\x11\n\tdimension\x18\x10 \x03(\t\x12\x1c\n\x14unittest_shard_index\x18\x11 \x01(\t\x12\x15\n\rtest_attempts\x18\x12 \x01(\t\x12\x13\n\x0bretry_level\x18\x13 \x01(\t\x12\x15\n\rstart_timeout\x18\x14 \x01(\t\x12\x14\n\x0ctest_timeout\x18\x15 \x01(\t\x12\x13\n\x0b\x62uilder_url\x18\x16 \x01(\t\x12\x17\n\x0fgcs_result_path\x18\x17 \x01(\t\x12\x33\n\tapk_tests\x18\x18 \x03(\x0b\x32 .on_device_tests_gateway.ApkTest\"r\n\x07\x41pkTest\x12\x13\n\x0btest_target\x18\x01 \x01(\t\x12\x10\n\x08\x61pk_path\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65vice_model\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65vice_pool\x18\x04 \x01(\t\x12\x15\n\rgtest_filters\x18\x05 \x01(\t\"s\n\x19OnDeviceTestsWatchCommand\x12\x0f\n\x07workdir\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x12\n\nsession_id\x18\x03 \x01(\t\x12\x11\n\tchange_id\x18\x04 \x01(\t\x12\x0f\n\x07\x64ry_run\x18\x05 \x01(\x08\")\n\x15OnDeviceTestsResponse\x12\x10\n\x08response\x18\x01 \x01(\t2\x8a\x02\n\x17on_device_tests_gateway\x12q\n\x0c\x65xec_command\x12-.on_device_tests_gateway.OnDeviceTestsCommand\x1a..on_device_tests_gateway.OnDeviceTestsResponse\"\x00\x30\x01\x12|\n\x12\x65xec_watch_command\x12\x32.on_device_tests_gateway.OnDeviceTestsWatchCommand\x1a..on_device_tests_gateway.OnDeviceTestsResponse\"\x00\x30\x01\x62\x06proto3') +) + + + + +_ONDEVICETESTSCOMMAND = _descriptor.Descriptor( + name='OnDeviceTestsCommand', + full_name='on_device_tests_gateway.OnDeviceTestsCommand', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='workdir', full_name='on_device_tests_gateway.OnDeviceTestsCommand.workdir', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='token', full_name='on_device_tests_gateway.OnDeviceTestsCommand.token', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_type', full_name='on_device_tests_gateway.OnDeviceTestsCommand.test_type', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='platform', full_name='on_device_tests_gateway.OnDeviceTestsCommand.platform', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='archive_path', full_name='on_device_tests_gateway.OnDeviceTestsCommand.archive_path', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='config', full_name='on_device_tests_gateway.OnDeviceTestsCommand.config', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tag', full_name='on_device_tests_gateway.OnDeviceTestsCommand.tag', index=6, + number=7, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='labels', full_name='on_device_tests_gateway.OnDeviceTestsCommand.labels', index=7, + number=8, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='builder_name', full_name='on_device_tests_gateway.OnDeviceTestsCommand.builder_name', index=8, + number=9, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='change_id', full_name='on_device_tests_gateway.OnDeviceTestsCommand.change_id', index=9, + number=10, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='build_number', full_name='on_device_tests_gateway.OnDeviceTestsCommand.build_number', index=10, + number=11, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='loader_platform', full_name='on_device_tests_gateway.OnDeviceTestsCommand.loader_platform', index=11, + number=12, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='loader_config', full_name='on_device_tests_gateway.OnDeviceTestsCommand.loader_config', index=12, + number=13, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='version', full_name='on_device_tests_gateway.OnDeviceTestsCommand.version', index=13, + number=14, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dry_run', full_name='on_device_tests_gateway.OnDeviceTestsCommand.dry_run', index=14, + number=15, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dimension', full_name='on_device_tests_gateway.OnDeviceTestsCommand.dimension', index=15, + number=16, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unittest_shard_index', full_name='on_device_tests_gateway.OnDeviceTestsCommand.unittest_shard_index', index=16, + number=17, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_attempts', full_name='on_device_tests_gateway.OnDeviceTestsCommand.test_attempts', index=17, + number=18, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='retry_level', full_name='on_device_tests_gateway.OnDeviceTestsCommand.retry_level', index=18, + number=19, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='start_timeout', full_name='on_device_tests_gateway.OnDeviceTestsCommand.start_timeout', index=19, + number=20, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='test_timeout', full_name='on_device_tests_gateway.OnDeviceTestsCommand.test_timeout', index=20, + number=21, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='builder_url', full_name='on_device_tests_gateway.OnDeviceTestsCommand.builder_url', index=21, + number=22, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='gcs_result_path', full_name='on_device_tests_gateway.OnDeviceTestsCommand.gcs_result_path', index=22, + number=23, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='apk_tests', full_name='on_device_tests_gateway.OnDeviceTestsCommand.apk_tests', index=23, + number=24, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=59, + serialized_end=599, +) + + +_APKTEST = _descriptor.Descriptor( + name='ApkTest', + full_name='on_device_tests_gateway.ApkTest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='test_target', full_name='on_device_tests_gateway.ApkTest.test_target', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='apk_path', full_name='on_device_tests_gateway.ApkTest.apk_path', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='device_model', full_name='on_device_tests_gateway.ApkTest.device_model', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='device_pool', full_name='on_device_tests_gateway.ApkTest.device_pool', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='gtest_filters', full_name='on_device_tests_gateway.ApkTest.gtest_filters', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=601, + serialized_end=715, +) + + +_ONDEVICETESTSWATCHCOMMAND = _descriptor.Descriptor( + name='OnDeviceTestsWatchCommand', + full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='workdir', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.workdir', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='token', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.token', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='session_id', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.session_id', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='change_id', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.change_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dry_run', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.dry_run', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=717, + serialized_end=832, +) + + +_ONDEVICETESTSRESPONSE = _descriptor.Descriptor( + name='OnDeviceTestsResponse', + full_name='on_device_tests_gateway.OnDeviceTestsResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='response', full_name='on_device_tests_gateway.OnDeviceTestsResponse.response', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=834, + serialized_end=875, +) + +_ONDEVICETESTSCOMMAND.fields_by_name['apk_tests'].message_type = _APKTEST +DESCRIPTOR.message_types_by_name['OnDeviceTestsCommand'] = _ONDEVICETESTSCOMMAND +DESCRIPTOR.message_types_by_name['ApkTest'] = _APKTEST +DESCRIPTOR.message_types_by_name['OnDeviceTestsWatchCommand'] = _ONDEVICETESTSWATCHCOMMAND +DESCRIPTOR.message_types_by_name['OnDeviceTestsResponse'] = _ONDEVICETESTSRESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +OnDeviceTestsCommand = _reflection.GeneratedProtocolMessageType('OnDeviceTestsCommand', (_message.Message,), dict( + DESCRIPTOR = _ONDEVICETESTSCOMMAND, + __module__ = 'on_device_tests_gateway_pb2' + # @@protoc_insertion_point(class_scope:on_device_tests_gateway.OnDeviceTestsCommand) + )) +_sym_db.RegisterMessage(OnDeviceTestsCommand) + +ApkTest = _reflection.GeneratedProtocolMessageType('ApkTest', (_message.Message,), dict( + DESCRIPTOR = _APKTEST, + __module__ = 'on_device_tests_gateway_pb2' + # @@protoc_insertion_point(class_scope:on_device_tests_gateway.ApkTest) + )) +_sym_db.RegisterMessage(ApkTest) + +OnDeviceTestsWatchCommand = _reflection.GeneratedProtocolMessageType('OnDeviceTestsWatchCommand', (_message.Message,), dict( + DESCRIPTOR = _ONDEVICETESTSWATCHCOMMAND, + __module__ = 'on_device_tests_gateway_pb2' + # @@protoc_insertion_point(class_scope:on_device_tests_gateway.OnDeviceTestsWatchCommand) + )) +_sym_db.RegisterMessage(OnDeviceTestsWatchCommand) + +OnDeviceTestsResponse = _reflection.GeneratedProtocolMessageType('OnDeviceTestsResponse', (_message.Message,), dict( + DESCRIPTOR = _ONDEVICETESTSRESPONSE, + __module__ = 'on_device_tests_gateway_pb2' + # @@protoc_insertion_point(class_scope:on_device_tests_gateway.OnDeviceTestsResponse) + )) +_sym_db.RegisterMessage(OnDeviceTestsResponse) + + + +_ON_DEVICE_TESTS_GATEWAY = _descriptor.ServiceDescriptor( + name='on_device_tests_gateway', + full_name='on_device_tests_gateway.on_device_tests_gateway', + file=DESCRIPTOR, + index=0, + options=None, + serialized_start=878, + serialized_end=1144, + methods=[ + _descriptor.MethodDescriptor( + name='exec_command', + full_name='on_device_tests_gateway.on_device_tests_gateway.exec_command', + index=0, + containing_service=None, + input_type=_ONDEVICETESTSCOMMAND, + output_type=_ONDEVICETESTSRESPONSE, + options=None, + ), + _descriptor.MethodDescriptor( + name='exec_watch_command', + full_name='on_device_tests_gateway.on_device_tests_gateway.exec_watch_command', + index=1, + containing_service=None, + input_type=_ONDEVICETESTSWATCHCOMMAND, + output_type=_ONDEVICETESTSRESPONSE, + options=None, + ), +]) +_sym_db.RegisterServiceDescriptor(_ON_DEVICE_TESTS_GATEWAY) + +DESCRIPTOR.services_by_name['on_device_tests_gateway'] = _ON_DEVICE_TESTS_GATEWAY + +# @@protoc_insertion_point(module_scope) diff --git a/tools/on_device_tests_gateway_pb2_grpc.py b/tools/on_device_tests_gateway_pb2_grpc.py new file mode 100644 index 0000000000000..fdbfa59ddf188 --- /dev/null +++ b/tools/on_device_tests_gateway_pb2_grpc.py @@ -0,0 +1,64 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + +import on_device_tests_gateway_pb2 as on__device__tests__gateway__pb2 + + +class on_device_tests_gatewayStub(object): + """Interface exported by the server. + """ + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.exec_command = channel.unary_stream( + '/on_device_tests_gateway.on_device_tests_gateway/exec_command', + request_serializer=on__device__tests__gateway__pb2.OnDeviceTestsCommand.SerializeToString, + response_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.FromString, + ) + self.exec_watch_command = channel.unary_stream( + '/on_device_tests_gateway.on_device_tests_gateway/exec_watch_command', + request_serializer=on__device__tests__gateway__pb2.OnDeviceTestsWatchCommand.SerializeToString, + response_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.FromString, + ) + + +class on_device_tests_gatewayServicer(object): + """Interface exported by the server. + """ + + def exec_command(self, request, context): + """A dumb proxy RPC service that passes user defined command line options + to the on-device tests gateway and streams back output in real time. + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def exec_watch_command(self, request, context): + # missing associated documentation comment in .proto file + pass + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_on_device_tests_gatewayServicer_to_server(servicer, server): + rpc_method_handlers = { + 'exec_command': grpc.unary_stream_rpc_method_handler( + servicer.exec_command, + request_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsCommand.FromString, + response_serializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.SerializeToString, + ), + 'exec_watch_command': grpc.unary_stream_rpc_method_handler( + servicer.exec_watch_command, + request_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsWatchCommand.FromString, + response_serializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.SerializeToString, + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'on_device_tests_gateway.on_device_tests_gateway', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) From 73d51b699cdf1c1227c701f7be3ebd3098d37e12 Mon Sep 17 00:00:00 2001 From: Igor Sarkisov Date: Mon, 23 Dec 2024 14:32:50 -0800 Subject: [PATCH 04/14] Incremental commit based on review comments --- .github/actions/on_device_tests/action.yaml | 78 +-------------------- 1 file changed, 1 insertion(+), 77 deletions(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index b03c0772535c8..9040a36d95ad7 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -26,7 +26,7 @@ runs: echo "DIMENSION=${{ matrix.dimension }}" >> $GITHUB_ENV fi shell: bash - - name: Run ${{ env.SHARD_NAME }} Tests on ${{ matrix.platform }} Platform + - name: Run Tests on ${{ matrix.platform }} Platform env: GCS_PATH: gs://${{ env.PROJECT_NAME }}-test-artifacts/${{ github.workflow }}/${{ github.run_number }}/${{ matrix.platform }}_${{ matrix.config }} run: | @@ -41,79 +41,3 @@ runs: --gcs_result_path "${GCS_RESULTS_PATH}" \ trigger \ shell: bash - - name: Download ${{ matrix.platform }} Test Results - if: always() && env.TEST_TYPE == 'unit_test' - run: | - # Don't break on error (-e), some commands are expected to fail. - set -ux - - COBALT_LOGS_DIR="${GITHUB_WORKSPACE}/cobalt_logs" - UNIT_TEST_RESULT_PATH="${GITHUB_WORKSPACE}/unit-test-results" - COBALT_XMLS_FILENAME="cobalt_xmls.zip" - - # Forward environment variables for uploading artifacts in later steps. - echo "UNIT_TEST_RESULT_PATH=${UNIT_TEST_RESULT_PATH}" >> $GITHUB_ENV - echo "COBALT_LOGS_DIR=${COBALT_LOGS_DIR}" >> $GITHUB_ENV - - mkdir -p "${GITHUB_WORKSPACE}/test_results" - cd "${GITHUB_WORKSPACE}/test_results" - - i=0 - # Try downloading the results for 6x 10 seconds before giving up. - while [ $i -lt 6 ]; do - # The results are uploaded after the test has completed. - sleep 10 - - # The log files are named by the device lab test driver. - COBALT_ERROR_LOG_FILENAME="webDriverTestLog.ERROR" - COBALT_INFO_LOG_FILENAME="webDriverTestLog.INFO" - - # This command will fail until the results have been uploaded. - gsutil cp "${GCS_RESULTS_PATH}/${COBALT_ERROR_LOG_FILENAME}" . - gsutil cp "${GCS_RESULTS_PATH}/${COBALT_INFO_LOG_FILENAME}" . - gsutil cp "${GCS_RESULTS_PATH}/${COBALT_XMLS_FILENAME}" . - - # Break if all files were downloaded. - if [[ -f "${COBALT_XMLS_FILENAME}" && -f "${COBALT_ERROR_LOG_FILENAME}" && -f "${COBALT_INFO_LOG_FILENAME}" ]]; then - break - fi - - i=$(( ${i} + 1 )) - done - - # Rename log files for archiving to not expose legacy weirdness. - mkdir -p "${COBALT_LOGS_DIR}/${{ matrix.platform }}/" - cp "${COBALT_ERROR_LOG_FILENAME}" "${COBALT_LOGS_DIR}/${{ matrix.platform }}/stderr_${{ matrix.shard }}.log" - cp "${COBALT_INFO_LOG_FILENAME}" "${COBALT_LOGS_DIR}/${{ matrix.platform }}/stdout_${{ matrix.shard }}.log" - - # Prepare unit test results for DataDog upload. - RESULT_PATH=${UNIT_TEST_RESULT_PATH}/${{ matrix.platform }}/${{ matrix.shard }}/ - mkdir -p ${RESULT_PATH} - - # Set tags for test differentiation. - tags="os.platform:${{ matrix.platform }}" - echo $tags > ${UNIT_TEST_RESULT_PATH}/${{ matrix.platform }}/TAGS - - unzip ${COBALT_XMLS_FILENAME} -d ${RESULT_PATH} - shell: bash - - name: Archive Unit Test Logs - uses: actions/upload-artifact@v3 - if: always() && env.TEST_TYPE == 'unit_test' - with: - name: Device logs - path: ${{ env.COBALT_LOGS_DIR }}/ - - name: Archive Unit Test Results - uses: actions/upload-artifact@v3 - if: always() && env.TEST_TYPE == 'unit_test' - with: - name: unit-test-results - path: ${{ env.UNIT_TEST_RESULT_PATH }}/ - - name: Print device logs - if: always() - run: | - if ls ${COBALT_LOGS_DIR}/**/*.log 1> /dev/null 2>&1; then - cat ${COBALT_LOGS_DIR}/**/*.log - else - echo "No device logs found" - fi - shell: bash From 99cc41d64b9bb9c9fe2828083b506735c38250e3 Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Thu, 2 Jan 2025 22:46:03 +0000 Subject: [PATCH 05/14] new changes for odt gateway --- .../android-arm/base_unittests_filter.json | 4 -- tools/on_device_tests_gateway.proto | 36 +++++-------- tools/on_device_tests_gateway_client.py | 54 ++++++------------- 3 files changed, 29 insertions(+), 65 deletions(-) diff --git a/cobalt/testing/android-arm/base_unittests_filter.json b/cobalt/testing/android-arm/base_unittests_filter.json index bb161c725dc43..fb7886542530b 100644 --- a/cobalt/testing/android-arm/base_unittests_filter.json +++ b/cobalt/testing/android-arm/base_unittests_filter.json @@ -2,9 +2,5 @@ "failing_tests": [ "BreakIteratorTest.BreakCharacter", "ValuesUtilTest.FilePath" - ], - "passing_tests": [ - "test1", - "test2" ] } diff --git a/tools/on_device_tests_gateway.proto b/tools/on_device_tests_gateway.proto index 50cc02d478f7e..933b5818faa4e 100644 --- a/tools/on_device_tests_gateway.proto +++ b/tools/on_device_tests_gateway.proto @@ -29,33 +29,23 @@ service on_device_tests_gateway { // Working directory and command line arguments to be passed to the gateway. message OnDeviceTestsCommand { - // Next ID: 23 string workdir = 1; string token = 2; - string test_type = 3; - string platform = 4; - string archive_path = 5; - string config = 6; - string tag = 7; - repeated string labels = 8; - string builder_name = 9; - string change_id = 10; - string build_number = 11; - string loader_platform = 12; - string loader_config = 13; - string version = 14; - bool dry_run = 15; - repeated string dimension = 16; - string unittest_shard_index = 17; - string test_attempts = 18; - string retry_level = 19; - string start_timeout = 20; - string test_timeout = 21; - string builder_url = 22; - string gcs_result_path = 23; - repeated ApkTest apk_tests = 24; + string platform = 3; + string archive_path = 4; + repeated string labels = 5; + string change_id = 6; + bool dry_run = 7; + repeated string dimension = 8; + string test_attempts = 9; + string retry_level = 10; + string start_timeout = 11; + string test_timeout = 12; + string gcs_result_path = 13; + repeated ApkTest apk_tests = 14; } +// apk_test details message ApkTest { string test_target = 1; string apk_path = 2; diff --git a/tools/on_device_tests_gateway_client.py b/tools/on_device_tests_gateway_client.py index 99cdbb5f7166a..2ff477bd00875 100644 --- a/tools/on_device_tests_gateway_client.py +++ b/tools/on_device_tests_gateway_client.py @@ -26,25 +26,15 @@ import on_device_tests_gateway_pb2 import on_device_tests_gateway_pb2_grpc -# All tests On-Device tests support -_TEST_TYPES = [ - 'black_box_test', - 'evergreen_test', - 'unit_test', -] - -# All test configs On-Device tests support -_TEST_CONFIGS = [ - 'devel', - 'staging', - 'production', -] - _WORK_DIR = '/on_device_tests_gateway' + +# Comment out thw next three lines for local testing _ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ( - #'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') - 'localhost') -#_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' + 'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') +_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' + +# Uncomment the next two lines for local testing +_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ('localhost') _ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '12345' @@ -75,23 +65,13 @@ def run_trigger_command(self, workdir: str, args: argparse.Namespace, apk_tests on_device_tests_gateway_pb2.OnDeviceTestsCommand( workdir=workdir, token=args.token, - #test_type=args.test_type, platform=args.platform, archive_path=args.archive_path, - #config=args.config, - #tag=args.tag, labels=args.label, gcs_result_path=args.gcs_result_path, - #builder_name=args.builder_name, - #builder_url=args.builder_url, change_id=args.change_id, - #build_number=args.build_number, - #loader_platform=args.loader_platform, - #loader_config=args.loader_config, - #version=args.version, dry_run=args.dry_run, dimension=args.dimension or [], - #unittest_shard_index=args.unittest_shard_index, test_attempts=args.test_attempts, retry_level=args.retry_level, apk_tests=apk_tests, @@ -131,10 +111,10 @@ def _read_json_config(filename): data = json.load(f) return data except FileNotFoundError: - #print(f" Config file '{filename}' not found.") + print(f" Config file '{filename}' not found.") return None except json.JSONDecodeError: - #print(f" Invalid JSON format in '{filename}'.") + print(f" Invalid JSON format in '{filename}'.") return None def _default_platform_json_file(platform): @@ -150,12 +130,12 @@ def _get_tests_filter_json_file(platform, gtest_target): def _process_apk_tests(args): apk_tests = [] platform_json_file = args.platform_json if args.platform_json else _default_platform_json_file(args.platform) - #print(' The platform_json_file is ' + platform_json_file) + print(f" The platform_json_file is '{platform_json_file}'") platform_json_file_data = _read_json_config(platform_json_file) gtest_device = platform_json_file_data["gtest_device"] gtest_lab = platform_json_file_data["gtest_lab"] gtest_blaze_target = "//experimental/cobalt/chrobalt_poc:custom_chrobalt_unit_tests_" + gtest_device - default_gtest_filters = "GURL*" + default_gtest_filters = "*" #print(' processing gtest_targets in json file') for gtest_target in platform_json_file_data["gtest_targets"]: @@ -170,22 +150,20 @@ def _process_apk_tests(args): gtest_filter_json_file_data = _read_json_config(gtest_filter_json_file) gtest_filters = default_gtest_filters if gtest_filter_json_file_data is None: - print(" This gtest_target does not have gtest_filters_specified"); + print(" This gtest_target does not have gtest_filters specified"); else: failing_tests_list = gtest_filter_json_file_data["failing_tests"] passing_tests_list = gtest_filter_json_file_data["passing_tests"] - #print(f" failing tests in json: {failing_tests_list}") - #print(f" passing tests in json: {passing_tests_list}") failing_tests_string = ":".join(failing_tests_list) passing_tests_string = ":".join(passing_tests_list) - #print(f" failing_tests_string = '{failing_tests_string}'") - #print(f" passing_tests_string = '{passing_tests_string}'") if passing_tests_string: gtest_filters += ":" + passing_tests_string if failing_tests_string: gtest_filters += ":-" + failing_tests_string - #print(f" gtest_filters = {gtest_filters}"); - apk_test["apk_path"] = "/bigstore/yt-temp/" + gtest_target + "-debug.apk" + print(f" gtest_filters = {gtest_filters}"); + + #apk_test["apk_path"] = "/bigstore/yt-temp/" + gtest_target + "-debug.apk" + apk_test["apk_path"] = "/bigstore/yt-temp/base_unittests-debug.apk" apk_test["gtest_filters"] = gtest_filters apk_tests.append(apk_test) From 46e17028e41b31e0caf6786fdef9097bddad2d72 Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Thu, 2 Jan 2025 23:54:04 +0000 Subject: [PATCH 06/14] additional changes to odt gateway code --- .github/actions/on_device_tests/action.yaml | 2 +- tools/on_device_tests_gateway_client.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index 9040a36d95ad7..1e61b0892b405 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -28,7 +28,7 @@ runs: shell: bash - name: Run Tests on ${{ matrix.platform }} Platform env: - GCS_PATH: gs://${{ env.PROJECT_NAME }}-test-artifacts/${{ github.workflow }}/${{ github.run_number }}/${{ matrix.platform }}_${{ matrix.config }} + GCS_PATH: /bigstore/${{ env.PROJECT_NAME }}-test-artifacts/${{ github.workflow }}/${{ github.run_number }}/${{ matrix.platform }}_${{ matrix.config }} run: | set -uxe python3 -u tools/on_device_tests_gateway_client.py \ diff --git a/tools/on_device_tests_gateway_client.py b/tools/on_device_tests_gateway_client.py index 2ff477bd00875..55937fd4b39ca 100644 --- a/tools/on_device_tests_gateway_client.py +++ b/tools/on_device_tests_gateway_client.py @@ -28,10 +28,10 @@ _WORK_DIR = '/on_device_tests_gateway' -# Comment out thw next three lines for local testing -_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ( - 'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') -_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' +# Comment out the next three lines for local testing +#_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ( +# 'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') +#_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' # Uncomment the next two lines for local testing _ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ('localhost') @@ -153,11 +153,11 @@ def _process_apk_tests(args): print(" This gtest_target does not have gtest_filters specified"); else: failing_tests_list = gtest_filter_json_file_data["failing_tests"] - passing_tests_list = gtest_filter_json_file_data["passing_tests"] + #passing_tests_list = gtest_filter_json_file_data["passing_tests"] failing_tests_string = ":".join(failing_tests_list) - passing_tests_string = ":".join(passing_tests_list) - if passing_tests_string: - gtest_filters += ":" + passing_tests_string + #passing_tests_string = ":".join(passing_tests_list) + #if passing_tests_string: + # gtest_filters += ":" + passing_tests_string if failing_tests_string: gtest_filters += ":-" + failing_tests_string print(f" gtest_filters = {gtest_filters}"); From cc7221601405ac63e5dd1d4e4dbe8edddb21a6cd Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Fri, 3 Jan 2025 00:36:28 +0000 Subject: [PATCH 07/14] changing --archive_path in action.yaml --- .github/actions/on_device_tests/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index 1e61b0892b405..a1e7fbe2542ed 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -37,7 +37,7 @@ runs: --token ${GITHUB_TOKEN} \ ${DIMENSION:+"--dimension" "$DIMENSION"} \ ${ON_DEVICE_TEST_ATTEMPTS:+"--test_attempts" "$ON_DEVICE_TEST_ATTEMPTS"} \ - --archive_path "${GCS_PATH}/artifacts.tar" \ + --archive_path "${GCS_PATH}" \ --gcs_result_path "${GCS_RESULTS_PATH}" \ trigger \ shell: bash From 11759a5a57145d084c84f1ddb7c8c4879030b99f Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Tue, 7 Jan 2025 00:50:48 +0000 Subject: [PATCH 08/14] Additional changes for odt gateway --- tools/on_device_tests_gateway_client.py | 30 +++++++++++-------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/tools/on_device_tests_gateway_client.py b/tools/on_device_tests_gateway_client.py index 55937fd4b39ca..78e91763bf02e 100644 --- a/tools/on_device_tests_gateway_client.py +++ b/tools/on_device_tests_gateway_client.py @@ -29,13 +29,13 @@ _WORK_DIR = '/on_device_tests_gateway' # Comment out the next three lines for local testing -#_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ( -# 'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') -#_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' +_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ( + 'on-device-tests-gateway-service.on-device-tests.svc.cluster.local') +_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '50052' # Uncomment the next two lines for local testing -_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ('localhost') -_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '12345' +#_ON_DEVICE_TESTS_GATEWAY_SERVICE_HOST = ('localhost') +#_ON_DEVICE_TESTS_GATEWAY_SERVICE_PORT = '12345' class OnDeviceTestsGatewayClient(): @@ -137,7 +137,6 @@ def _process_apk_tests(args): gtest_blaze_target = "//experimental/cobalt/chrobalt_poc:custom_chrobalt_unit_tests_" + gtest_device default_gtest_filters = "*" - #print(' processing gtest_targets in json file') for gtest_target in platform_json_file_data["gtest_targets"]: apk_test = { "test_target": gtest_blaze_target, @@ -153,17 +152,13 @@ def _process_apk_tests(args): print(" This gtest_target does not have gtest_filters specified"); else: failing_tests_list = gtest_filter_json_file_data["failing_tests"] - #passing_tests_list = gtest_filter_json_file_data["passing_tests"] failing_tests_string = ":".join(failing_tests_list) - #passing_tests_string = ":".join(passing_tests_list) - #if passing_tests_string: - # gtest_filters += ":" + passing_tests_string if failing_tests_string: gtest_filters += ":-" + failing_tests_string print(f" gtest_filters = {gtest_filters}"); - #apk_test["apk_path"] = "/bigstore/yt-temp/" + gtest_target + "-debug.apk" - apk_test["apk_path"] = "/bigstore/yt-temp/base_unittests-debug.apk" + apk_test["apk_path"] = f"{args.archive_path}/{gtest_target}-debug.apk" + #apk_test["apk_path"] = "/bigstore/yt-temp/base_unittests-debug.apk" apk_test["gtest_filters"] = gtest_filters apk_tests.append(apk_test) @@ -178,11 +173,12 @@ def main(): level=logging.INFO, format='[%(filename)s:%(lineno)s] %(message)s') parser = argparse.ArgumentParser( - epilog=('Example: ./on_device_tests_gateway_client.py ' - '--test_type=unit_test ' - '--remote_archive_path=gs://my_bucket/path/to/artifacts.tar ' - '--platform=raspi-2 ' - '--config=devel'), + epilog=('Example: ./on_device_tests_gateway_client.py' + 'trigger' + '--token token1' + '--platform android-arm' + '--archive_path /bigstore/yt-temp' + '--dimension host_name=regex:maneki-mhserver-05.*'), formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '-t', From 14f963f3ed9ded4471dd3a1007973ee91c8d93ac Mon Sep 17 00:00:00 2001 From: Igor Sarkisov Date: Tue, 7 Jan 2025 11:21:00 -0800 Subject: [PATCH 09/14] Add additional argument for ODT gateway client --- .github/actions/on_device_tests/action.yaml | 32 ++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index a1e7fbe2542ed..d4f26042e2614 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -29,15 +29,45 @@ runs: - name: Run Tests on ${{ matrix.platform }} Platform env: GCS_PATH: /bigstore/${{ env.PROJECT_NAME }}-test-artifacts/${{ github.workflow }}/${{ github.run_number }}/${{ matrix.platform }}_${{ matrix.config }} + GITHUB_SHA: ${{ github.sha }} + GITHUB_TOKEN: ${{ github.token }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + GITHUB_ACTOR: ${{ github.actor }} + GITHUB_TRIGGERING_ACTOR: ${{ github.triggering_actor }} + GITHUB_ACTOR_ID: ${{ github.actor_id }} + GITHUB_REPO: ${{ github.repository }} + GITHUB_PR_HEAD_USER_LOGIN: ${{ github.event.pull_request.head.user.login }} + GITHUB_PR_HEAD_USER_ID: ${{ github.event.pull_request.head.user.id }} + GITHUB_COMMIT_AUTHOR_USERNAME: ${{ github.event.commits[0].author.username }} + GITHUB_COMMIT_AUTHOR_EMAIL: ${{ github.event.commits[0].author.email }} + GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }} + GITHUB_RUN_NUMBER: ${{ github.run_number }} + GITHUB_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GITHUB_WORKFLOW: ${{ github.workflow }} run: | set -uxe python3 -u tools/on_device_tests_gateway_client.py \ --platform_json "${GITHUB_WORKSPACE}/src/.github/config/${{ matrix.platform}}.json" \ --filter_json_dir "${GITHUB_WORKSPACE}/src/cobalt/testing/${{ matrix.platform}}" \ --token ${GITHUB_TOKEN} \ + --change_id ${GITHUB_PR_NUMBER:-postsubmit} \ + --tag cobalt_github_${GITHUB_EVENT_NAME} \ + --builder_name github_${{ matrix.platform }}_tests \ + --build_number ${GITHUB_RUN_NUMBER} \ + --builder_url ${GITHUB_RUN_URL} \ + --label github \ + --label ${GITHUB_EVENT_NAME} \ + --label ${GITHUB_WORKFLOW} \ + --label actor-${GITHUB_ACTOR} \ + --label actor_id-${GITHUB_ACTOR_ID} \ + --label triggering_actor-${GITHUB_TRIGGERING_ACTOR} \ + --label sha-${GITHUB_SHA} \ + --label repository-${GITHUB_REPO} \ + --label author-${GITHUB_PR_HEAD_USER_LOGIN:-$GITHUB_COMMIT_AUTHOR_USERNAME} \ + --label author_id-${GITHUB_PR_HEAD_USER_ID:-$GITHUB_COMMIT_AUTHOR_EMAIL} ${DIMENSION:+"--dimension" "$DIMENSION"} \ ${ON_DEVICE_TEST_ATTEMPTS:+"--test_attempts" "$ON_DEVICE_TEST_ATTEMPTS"} \ --archive_path "${GCS_PATH}" \ --gcs_result_path "${GCS_RESULTS_PATH}" \ - trigger \ + trigger shell: bash From 3ecc7aa332610c6f4e46454723fdf3b471ac160e Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Tue, 7 Jan 2025 19:20:46 +0000 Subject: [PATCH 10/14] Additional improvements for odt gateway code --- tools/on_device_tests_gateway_client.py | 392 +++++++++++++++--------- 1 file changed, 244 insertions(+), 148 deletions(-) diff --git a/tools/on_device_tests_gateway_client.py b/tools/on_device_tests_gateway_client.py index 78e91763bf02e..2cfad00758fce 100644 --- a/tools/on_device_tests_gateway_client.py +++ b/tools/on_device_tests_gateway_client.py @@ -117,162 +117,258 @@ def _read_json_config(filename): print(f" Invalid JSON format in '{filename}'.") return None -def _default_platform_json_file(platform): - current_dir = os.path.dirname(os.path.abspath(__file__)) - relative_path = os.path.join("..", ".github", "config", platform + ".json") - return os.path.join(current_dir, relative_path) +def _get_platform_json_file(platform): + """Constructs the path to the platform JSON configuration file. + + Args: + platform: The name of the platform. + + Returns: + The absolute path to the platform JSON file. + """ + return os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + ".github", + "config", + f"{platform}.json" + ) def _get_tests_filter_json_file(platform, gtest_target): - current_dir = os.path.dirname(os.path.abspath(__file__)) - relative_path = os.path.join("..", "cobalt", "testing", platform, gtest_target + "_filter.json") - return os.path.join(current_dir, relative_path) + """Constructs the path to the gtest filter JSON file. + + Args: + platform: The name of the platform. + gtest_target: The name of the gtest target. + + Returns: + The absolute path to the gtest filter JSON file. + """ + return os.path.join( + os.path.dirname(os.path.abspath(__file__)), + "..", + "cobalt", + "testing", + platform, + f"{gtest_target}_filter.json" + ) def _process_apk_tests(args): - apk_tests = [] - platform_json_file = args.platform_json if args.platform_json else _default_platform_json_file(args.platform) - print(f" The platform_json_file is '{platform_json_file}'") - platform_json_file_data = _read_json_config(platform_json_file) - gtest_device = platform_json_file_data["gtest_device"] - gtest_lab = platform_json_file_data["gtest_lab"] - gtest_blaze_target = "//experimental/cobalt/chrobalt_poc:custom_chrobalt_unit_tests_" + gtest_device - default_gtest_filters = "*" - - for gtest_target in platform_json_file_data["gtest_targets"]: - apk_test = { - "test_target": gtest_blaze_target, - "device_model": gtest_device, - "device_pool": gtest_lab - } - print(f" gtest_target: {gtest_target}") - gtest_filter_json_file = _get_tests_filter_json_file(args.platform, gtest_target) - print(f" gtest_filter_json_file = {gtest_filter_json_file}") - gtest_filter_json_file_data = _read_json_config(gtest_filter_json_file) - gtest_filters = default_gtest_filters - if gtest_filter_json_file_data is None: - print(" This gtest_target does not have gtest_filters specified"); - else: - failing_tests_list = gtest_filter_json_file_data["failing_tests"] - failing_tests_string = ":".join(failing_tests_list) - if failing_tests_string: - gtest_filters += ":-" + failing_tests_string - print(f" gtest_filters = {gtest_filters}"); + """Processes APK tests based on provided arguments. - apk_test["apk_path"] = f"{args.archive_path}/{gtest_target}-debug.apk" - #apk_test["apk_path"] = "/bigstore/yt-temp/base_unittests-debug.apk" - apk_test["gtest_filters"] = gtest_filters - apk_tests.append(apk_test) + Args: + args: An argparse.Namespace object containing the following attributes: + platform: The platform for the tests. + platform_json: Optional path to a platform JSON file. + blaze_targets: A list of Blaze targets. + archive_path: Path to the archive containing APKs. + + Returns: + A list of dictionaries, where each dictionary represents an APK test + with keys like "test_target", "device_model", "device_pool", + "apk_path", and "gtest_filters". + """ - print(f" apk_tests: {apk_tests}") - return apk_tests + apk_tests = [] + platform_json_file = args.platform_json or _default_platform_json_file(args.platform) + print(f"The platform_json_file is '{platform_json_file}'") + platform_data = _read_json_config(platform_json_file) + print(f"Loaded platform data: {platform_data}") # Added verbosity + + for target in args.blaze_targets: + print(f"Processing Blaze target: {target}") # Added verbosity + for gtest_target in platform_data["gtest_targets"]: + print(f" Processing gtest_target: {gtest_target}") # Added verbosity + apk_test = { + "test_target": target, + "device_model": platform_data["gtest_device"], + "device_pool": platform_data["gtest_lab"], + "apk_path": f"{args.archive_path}/{gtest_target}-debug.apk", + "gtest_filters": _get_gtest_filters(args.platform, gtest_target) + } + apk_tests.append(apk_test) + print(f" Created apk_test: {apk_test}") # Added verbosity + + print(f"apk_tests: {apk_tests}") + return apk_tests + + +def _get_gtest_filters(platform, gtest_target): + """Retrieves gtest filters for a given target. -def main(): - """Main routine.""" - print('Starting main routine') - - logging.basicConfig( - level=logging.INFO, format='[%(filename)s:%(lineno)s] %(message)s') - - parser = argparse.ArgumentParser( - epilog=('Example: ./on_device_tests_gateway_client.py' - 'trigger' - '--token token1' - '--platform android-arm' - '--archive_path /bigstore/yt-temp' - '--dimension host_name=regex:maneki-mhserver-05.*'), - formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument( - '-t', - '--token', - type=str, - required=True, - help='On Device Tests authentication token') - parser.add_argument( - '--dry_run', - action='store_true', - help='Specifies to show what would be done without actually doing it.') - parser.add_argument( - '-i', - '--change_id', - type=str, - help='ChangeId that triggered this test, if any. ' - 'Saved with performance test results.') - - subparsers = parser.add_subparsers( - dest='action', help='On-Device tests commands', required=True) - trigger_parser = subparsers.add_parser( - 'trigger', help='Trigger On-Device tests') - - trigger_parser.add_argument( - '-p', - '--platform', - type=str, - required=True, - help='Platform this test was built for.') - trigger_parser.add_argument( - '-pf', - '--platform_json', - type=str, - help='Platform-specific json file containing the list of target tests.') - trigger_parser.add_argument( - '-a', - '--archive_path', - type=str, - required=True, - help='Path to Chrobalt archive to be tested. Must be on gcs.') - trigger_parser.add_argument( - '-l', - '--label', - type=str, - default=[], - action='append', - help='Additional labels to assign to the test.') - trigger_parser.add_argument( - '--gcs_result_path', - type=str, - help='GCS url where test result files should be uploaded.') - trigger_parser.add_argument( - '--dimension', - type=str, - action='append', - help='On-Device Tests dimension used to select a device. ' - 'Must have the following form: =.' - ' E.G. "release_version=regex:10.*') - trigger_parser.add_argument( - '--test_attempts', - type=str, - default='1', - required=False, - help='The maximum number of times a test could retry.') - trigger_parser.add_argument( - '--retry_level', - type=str, - default='ERROR', - required=False, - help='The retry level of Mobile harness job. Either ERROR (to retry for ' - 'MH errors) or FAIL (to retry for failing tests). Setting retry_level to ' - 'FAIL will also retry for MH errors.') - - watch_parser = subparsers.add_parser('watch', help='Trigger On-Device tests') - watch_parser.add_argument( - 'session_id', - type=str, - help='Session id of a previously triggered mobile ' - 'harness test. If passed, the test will not be ' - 'triggered, but will be watched until the exit ' - 'status is reached.') - - args = parser.parse_args() - apk_tests = _process_apk_tests(args) - - client = OnDeviceTestsGatewayClient() - try: - if args.action == 'trigger': - client.run_trigger_command(workdir=_WORK_DIR, args=args, apk_tests=apk_tests) + Args: + platform: The platform for the tests. + gtest_target: The name of the gtest target. + + Returns: + A string representing the gtest filters. + """ + + gtest_filters = "*" + filter_json_file = _get_tests_filter_json_file(platform, gtest_target) + print(f" gtest_filter_json_file = {filter_json_file}") + filter_data = _read_json_config(filter_json_file) + if filter_data: + print(f" Loaded filter data: {filter_data}") # Added verbosity + failing_tests = ":".join(filter_data.get("failing_tests", [])) + if failing_tests: + gtest_filters += ":-" + failing_tests + print(f" gtest_filters = {gtest_filters}") else: - client.run_watch_command(workdir=_WORK_DIR, args=args) - except grpc.RpcError as e: - print(e) - return e.code().value + print(f" This gtest_target does not have gtest_filters specified") + return gtest_filters + + +def main(): + """Main routine for the on-device tests gateway client.""" + + logging.basicConfig( + level=logging.INFO, + format='[%(filename)s:%(lineno)s] %(message)s' + ) + print('Starting main routine') + + parser = argparse.ArgumentParser( + description="Client for interacting with the On-Device Tests gateway.", + epilog=( + 'Example: ./on_device_tests_gateway_client.py trigger ' + '--token token1 ' + '--platform android-arm ' + '--archive_path /bigstore/yt-temp ' + '--blaze_targets //experimental/cobalt/chrobalt_poc:chrobalt_unit_tests_maneki_sabrina //experimental/cobalt/chrobalt_poc:chrobalt_unit_tests_shared_boreal ' + '--dimension host_name=regex:maneki-mhserver-05.*' + ), + formatter_class=argparse.RawDescriptionHelpFormatter + ) + + # Authentication + parser.add_argument( + '-t', + '--token', + type=str, + required=True, + help='On Device Tests authentication token' + ) + + # General options + parser.add_argument( + '--dry_run', + action='store_true', + help='Show what would be done without actually doing it.' + ) + parser.add_argument( + '-i', + '--change_id', + type=str, + help='ChangeId that triggered this test, if any. Saved with performance test results.' + ) + + subparsers = parser.add_subparsers( + dest='action', + help='On-Device tests commands', + required=True + ) + + # Trigger command + trigger_parser = subparsers.add_parser( + 'trigger', + help='Trigger On-Device tests', + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + trigger_parser.add_argument( + '-p', + '--platform', + type=str, + required=True, + help='Platform this test was built for.' + ) + trigger_parser.add_argument( + '-pf', + '--platform_json', + type=str, + help='Platform-specific JSON file containing the list of target tests.' + ) + trigger_parser.add_argument( + '-a', + '--archive_path', + type=str, + required=True, + help='Path to Chrobalt archive to be tested. Must be on GCS.' + ) + trigger_parser.add_argument( + '-l', + '--label', + type=str, + action='append', + default=[], + help='Additional labels to assign to the test.' + ) + trigger_parser.add_argument( + '--gcs_result_path', + type=str, + help='GCS URL where test result files should be uploaded.' + ) + trigger_parser.add_argument( + '--dimension', + type=str, + action='append', + help=( + 'On-Device Tests dimension used to select a device. ' + 'Must have the following form: =. ' + 'E.G. "release_version=regex:10.*"' + ) + ) + trigger_parser.add_argument( + '--test_attempts', + type=str, + default='1', + help='The maximum number of times a test could retry.' + ) + trigger_parser.add_argument( + '--blaze_targets', + nargs="+", + type=str, + required=True, + help='A list of Blaze targets to run.' + ) + trigger_parser.add_argument( + '--retry_level', + type=str, + default='ERROR', + choices=['ERROR', 'FAIL'], + help=( + 'The retry level of Mobile Harness job. ' + 'ERROR to retry for MH errors, ' + 'FAIL to retry for failing tests (and MH errors).' + ) + ) + + # Watch command + watch_parser = subparsers.add_parser( + 'watch', + help='Watch a previously triggered On-Device test' + ) + watch_parser.add_argument( + 'session_id', + type=str, + help=( + 'Session ID of a previously triggered Mobile Harness test. ' + 'The test will be watched until it completes.' + ) + ) + + args = parser.parse_args() + apk_tests = _process_apk_tests(args) + + client = OnDeviceTestsGatewayClient() + try: + if args.action == 'trigger': + client.run_trigger_command(workdir=_WORK_DIR, args=args, apk_tests=apk_tests) + else: + client.run_watch_command(workdir=_WORK_DIR, args=args) + except grpc.RpcError as e: + print(e) + return e.code().value if __name__ == '__main__': From a93365cb0b6868b40f556c750a6aaca193262b18 Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Tue, 7 Jan 2025 19:37:40 +0000 Subject: [PATCH 11/14] removing autogenerated files from pr --- tools/on_device_tests_gateway_pb2.py | 437 ---------------------- tools/on_device_tests_gateway_pb2_grpc.py | 64 ---- 2 files changed, 501 deletions(-) delete mode 100644 tools/on_device_tests_gateway_pb2.py delete mode 100644 tools/on_device_tests_gateway_pb2_grpc.py diff --git a/tools/on_device_tests_gateway_pb2.py b/tools/on_device_tests_gateway_pb2.py deleted file mode 100644 index f6c8947b850fa..0000000000000 --- a/tools/on_device_tests_gateway_pb2.py +++ /dev/null @@ -1,437 +0,0 @@ -# Generated by the protocol buffer compiler. DO NOT EDIT! -# source: on_device_tests_gateway.proto - -import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) -from google.protobuf import descriptor as _descriptor -from google.protobuf import message as _message -from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database -from google.protobuf import descriptor_pb2 -# @@protoc_insertion_point(imports) - -_sym_db = _symbol_database.Default() - - - - -DESCRIPTOR = _descriptor.FileDescriptor( - name='on_device_tests_gateway.proto', - package='on_device_tests_gateway', - syntax='proto3', - serialized_pb=_b('\n\x1don_device_tests_gateway.proto\x12\x17on_device_tests_gateway\"\x9c\x04\n\x14OnDeviceTestsCommand\x12\x0f\n\x07workdir\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x11\n\ttest_type\x18\x03 \x01(\t\x12\x10\n\x08platform\x18\x04 \x01(\t\x12\x14\n\x0c\x61rchive_path\x18\x05 \x01(\t\x12\x0e\n\x06\x63onfig\x18\x06 \x01(\t\x12\x0b\n\x03tag\x18\x07 \x01(\t\x12\x0e\n\x06labels\x18\x08 \x03(\t\x12\x14\n\x0c\x62uilder_name\x18\t \x01(\t\x12\x11\n\tchange_id\x18\n \x01(\t\x12\x14\n\x0c\x62uild_number\x18\x0b \x01(\t\x12\x17\n\x0floader_platform\x18\x0c \x01(\t\x12\x15\n\rloader_config\x18\r \x01(\t\x12\x0f\n\x07version\x18\x0e \x01(\t\x12\x0f\n\x07\x64ry_run\x18\x0f \x01(\x08\x12\x11\n\tdimension\x18\x10 \x03(\t\x12\x1c\n\x14unittest_shard_index\x18\x11 \x01(\t\x12\x15\n\rtest_attempts\x18\x12 \x01(\t\x12\x13\n\x0bretry_level\x18\x13 \x01(\t\x12\x15\n\rstart_timeout\x18\x14 \x01(\t\x12\x14\n\x0ctest_timeout\x18\x15 \x01(\t\x12\x13\n\x0b\x62uilder_url\x18\x16 \x01(\t\x12\x17\n\x0fgcs_result_path\x18\x17 \x01(\t\x12\x33\n\tapk_tests\x18\x18 \x03(\x0b\x32 .on_device_tests_gateway.ApkTest\"r\n\x07\x41pkTest\x12\x13\n\x0btest_target\x18\x01 \x01(\t\x12\x10\n\x08\x61pk_path\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65vice_model\x18\x03 \x01(\t\x12\x13\n\x0b\x64\x65vice_pool\x18\x04 \x01(\t\x12\x15\n\rgtest_filters\x18\x05 \x01(\t\"s\n\x19OnDeviceTestsWatchCommand\x12\x0f\n\x07workdir\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t\x12\x12\n\nsession_id\x18\x03 \x01(\t\x12\x11\n\tchange_id\x18\x04 \x01(\t\x12\x0f\n\x07\x64ry_run\x18\x05 \x01(\x08\")\n\x15OnDeviceTestsResponse\x12\x10\n\x08response\x18\x01 \x01(\t2\x8a\x02\n\x17on_device_tests_gateway\x12q\n\x0c\x65xec_command\x12-.on_device_tests_gateway.OnDeviceTestsCommand\x1a..on_device_tests_gateway.OnDeviceTestsResponse\"\x00\x30\x01\x12|\n\x12\x65xec_watch_command\x12\x32.on_device_tests_gateway.OnDeviceTestsWatchCommand\x1a..on_device_tests_gateway.OnDeviceTestsResponse\"\x00\x30\x01\x62\x06proto3') -) - - - - -_ONDEVICETESTSCOMMAND = _descriptor.Descriptor( - name='OnDeviceTestsCommand', - full_name='on_device_tests_gateway.OnDeviceTestsCommand', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='workdir', full_name='on_device_tests_gateway.OnDeviceTestsCommand.workdir', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='token', full_name='on_device_tests_gateway.OnDeviceTestsCommand.token', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='test_type', full_name='on_device_tests_gateway.OnDeviceTestsCommand.test_type', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='platform', full_name='on_device_tests_gateway.OnDeviceTestsCommand.platform', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='archive_path', full_name='on_device_tests_gateway.OnDeviceTestsCommand.archive_path', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='config', full_name='on_device_tests_gateway.OnDeviceTestsCommand.config', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='tag', full_name='on_device_tests_gateway.OnDeviceTestsCommand.tag', index=6, - number=7, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='labels', full_name='on_device_tests_gateway.OnDeviceTestsCommand.labels', index=7, - number=8, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='builder_name', full_name='on_device_tests_gateway.OnDeviceTestsCommand.builder_name', index=8, - number=9, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='change_id', full_name='on_device_tests_gateway.OnDeviceTestsCommand.change_id', index=9, - number=10, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='build_number', full_name='on_device_tests_gateway.OnDeviceTestsCommand.build_number', index=10, - number=11, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='loader_platform', full_name='on_device_tests_gateway.OnDeviceTestsCommand.loader_platform', index=11, - number=12, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='loader_config', full_name='on_device_tests_gateway.OnDeviceTestsCommand.loader_config', index=12, - number=13, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='version', full_name='on_device_tests_gateway.OnDeviceTestsCommand.version', index=13, - number=14, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='dry_run', full_name='on_device_tests_gateway.OnDeviceTestsCommand.dry_run', index=14, - number=15, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='dimension', full_name='on_device_tests_gateway.OnDeviceTestsCommand.dimension', index=15, - number=16, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unittest_shard_index', full_name='on_device_tests_gateway.OnDeviceTestsCommand.unittest_shard_index', index=16, - number=17, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='test_attempts', full_name='on_device_tests_gateway.OnDeviceTestsCommand.test_attempts', index=17, - number=18, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='retry_level', full_name='on_device_tests_gateway.OnDeviceTestsCommand.retry_level', index=18, - number=19, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='start_timeout', full_name='on_device_tests_gateway.OnDeviceTestsCommand.start_timeout', index=19, - number=20, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='test_timeout', full_name='on_device_tests_gateway.OnDeviceTestsCommand.test_timeout', index=20, - number=21, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='builder_url', full_name='on_device_tests_gateway.OnDeviceTestsCommand.builder_url', index=21, - number=22, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='gcs_result_path', full_name='on_device_tests_gateway.OnDeviceTestsCommand.gcs_result_path', index=22, - number=23, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='apk_tests', full_name='on_device_tests_gateway.OnDeviceTestsCommand.apk_tests', index=23, - number=24, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=59, - serialized_end=599, -) - - -_APKTEST = _descriptor.Descriptor( - name='ApkTest', - full_name='on_device_tests_gateway.ApkTest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='test_target', full_name='on_device_tests_gateway.ApkTest.test_target', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='apk_path', full_name='on_device_tests_gateway.ApkTest.apk_path', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='device_model', full_name='on_device_tests_gateway.ApkTest.device_model', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='device_pool', full_name='on_device_tests_gateway.ApkTest.device_pool', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='gtest_filters', full_name='on_device_tests_gateway.ApkTest.gtest_filters', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=601, - serialized_end=715, -) - - -_ONDEVICETESTSWATCHCOMMAND = _descriptor.Descriptor( - name='OnDeviceTestsWatchCommand', - full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='workdir', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.workdir', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='token', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.token', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='session_id', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.session_id', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='change_id', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.change_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='dry_run', full_name='on_device_tests_gateway.OnDeviceTestsWatchCommand.dry_run', index=4, - number=5, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=717, - serialized_end=832, -) - - -_ONDEVICETESTSRESPONSE = _descriptor.Descriptor( - name='OnDeviceTestsResponse', - full_name='on_device_tests_gateway.OnDeviceTestsResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='response', full_name='on_device_tests_gateway.OnDeviceTestsResponse.response', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=834, - serialized_end=875, -) - -_ONDEVICETESTSCOMMAND.fields_by_name['apk_tests'].message_type = _APKTEST -DESCRIPTOR.message_types_by_name['OnDeviceTestsCommand'] = _ONDEVICETESTSCOMMAND -DESCRIPTOR.message_types_by_name['ApkTest'] = _APKTEST -DESCRIPTOR.message_types_by_name['OnDeviceTestsWatchCommand'] = _ONDEVICETESTSWATCHCOMMAND -DESCRIPTOR.message_types_by_name['OnDeviceTestsResponse'] = _ONDEVICETESTSRESPONSE -_sym_db.RegisterFileDescriptor(DESCRIPTOR) - -OnDeviceTestsCommand = _reflection.GeneratedProtocolMessageType('OnDeviceTestsCommand', (_message.Message,), dict( - DESCRIPTOR = _ONDEVICETESTSCOMMAND, - __module__ = 'on_device_tests_gateway_pb2' - # @@protoc_insertion_point(class_scope:on_device_tests_gateway.OnDeviceTestsCommand) - )) -_sym_db.RegisterMessage(OnDeviceTestsCommand) - -ApkTest = _reflection.GeneratedProtocolMessageType('ApkTest', (_message.Message,), dict( - DESCRIPTOR = _APKTEST, - __module__ = 'on_device_tests_gateway_pb2' - # @@protoc_insertion_point(class_scope:on_device_tests_gateway.ApkTest) - )) -_sym_db.RegisterMessage(ApkTest) - -OnDeviceTestsWatchCommand = _reflection.GeneratedProtocolMessageType('OnDeviceTestsWatchCommand', (_message.Message,), dict( - DESCRIPTOR = _ONDEVICETESTSWATCHCOMMAND, - __module__ = 'on_device_tests_gateway_pb2' - # @@protoc_insertion_point(class_scope:on_device_tests_gateway.OnDeviceTestsWatchCommand) - )) -_sym_db.RegisterMessage(OnDeviceTestsWatchCommand) - -OnDeviceTestsResponse = _reflection.GeneratedProtocolMessageType('OnDeviceTestsResponse', (_message.Message,), dict( - DESCRIPTOR = _ONDEVICETESTSRESPONSE, - __module__ = 'on_device_tests_gateway_pb2' - # @@protoc_insertion_point(class_scope:on_device_tests_gateway.OnDeviceTestsResponse) - )) -_sym_db.RegisterMessage(OnDeviceTestsResponse) - - - -_ON_DEVICE_TESTS_GATEWAY = _descriptor.ServiceDescriptor( - name='on_device_tests_gateway', - full_name='on_device_tests_gateway.on_device_tests_gateway', - file=DESCRIPTOR, - index=0, - options=None, - serialized_start=878, - serialized_end=1144, - methods=[ - _descriptor.MethodDescriptor( - name='exec_command', - full_name='on_device_tests_gateway.on_device_tests_gateway.exec_command', - index=0, - containing_service=None, - input_type=_ONDEVICETESTSCOMMAND, - output_type=_ONDEVICETESTSRESPONSE, - options=None, - ), - _descriptor.MethodDescriptor( - name='exec_watch_command', - full_name='on_device_tests_gateway.on_device_tests_gateway.exec_watch_command', - index=1, - containing_service=None, - input_type=_ONDEVICETESTSWATCHCOMMAND, - output_type=_ONDEVICETESTSRESPONSE, - options=None, - ), -]) -_sym_db.RegisterServiceDescriptor(_ON_DEVICE_TESTS_GATEWAY) - -DESCRIPTOR.services_by_name['on_device_tests_gateway'] = _ON_DEVICE_TESTS_GATEWAY - -# @@protoc_insertion_point(module_scope) diff --git a/tools/on_device_tests_gateway_pb2_grpc.py b/tools/on_device_tests_gateway_pb2_grpc.py deleted file mode 100644 index fdbfa59ddf188..0000000000000 --- a/tools/on_device_tests_gateway_pb2_grpc.py +++ /dev/null @@ -1,64 +0,0 @@ -# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! -import grpc - -import on_device_tests_gateway_pb2 as on__device__tests__gateway__pb2 - - -class on_device_tests_gatewayStub(object): - """Interface exported by the server. - """ - - def __init__(self, channel): - """Constructor. - - Args: - channel: A grpc.Channel. - """ - self.exec_command = channel.unary_stream( - '/on_device_tests_gateway.on_device_tests_gateway/exec_command', - request_serializer=on__device__tests__gateway__pb2.OnDeviceTestsCommand.SerializeToString, - response_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.FromString, - ) - self.exec_watch_command = channel.unary_stream( - '/on_device_tests_gateway.on_device_tests_gateway/exec_watch_command', - request_serializer=on__device__tests__gateway__pb2.OnDeviceTestsWatchCommand.SerializeToString, - response_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.FromString, - ) - - -class on_device_tests_gatewayServicer(object): - """Interface exported by the server. - """ - - def exec_command(self, request, context): - """A dumb proxy RPC service that passes user defined command line options - to the on-device tests gateway and streams back output in real time. - """ - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - def exec_watch_command(self, request, context): - # missing associated documentation comment in .proto file - pass - context.set_code(grpc.StatusCode.UNIMPLEMENTED) - context.set_details('Method not implemented!') - raise NotImplementedError('Method not implemented!') - - -def add_on_device_tests_gatewayServicer_to_server(servicer, server): - rpc_method_handlers = { - 'exec_command': grpc.unary_stream_rpc_method_handler( - servicer.exec_command, - request_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsCommand.FromString, - response_serializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.SerializeToString, - ), - 'exec_watch_command': grpc.unary_stream_rpc_method_handler( - servicer.exec_watch_command, - request_deserializer=on__device__tests__gateway__pb2.OnDeviceTestsWatchCommand.FromString, - response_serializer=on__device__tests__gateway__pb2.OnDeviceTestsResponse.SerializeToString, - ), - } - generic_handler = grpc.method_handlers_generic_handler( - 'on_device_tests_gateway.on_device_tests_gateway', rpc_method_handlers) - server.add_generic_rpc_handlers((generic_handler,)) From 57420eb2d8b04b51c70125488a459ff75861558e Mon Sep 17 00:00:00 2001 From: Felipe Mira Date: Tue, 7 Jan 2025 19:58:14 +0000 Subject: [PATCH 12/14] moving odt gateway code from tools folder to cobalt/tools --- .github/actions/on_device_tests/action.yaml | 4 ++-- {tools => cobalt/tools}/on_device_tests_gateway.proto | 0 {tools => cobalt/tools}/on_device_tests_gateway_client.py | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {tools => cobalt/tools}/on_device_tests_gateway.proto (100%) rename {tools => cobalt/tools}/on_device_tests_gateway_client.py (100%) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index d4f26042e2614..478772a450ea8 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -10,7 +10,7 @@ runs: shell: bash - name: Generate gRPC files run: | - python -m grpc_tools.protoc -Itools/ --python_out=tools/ --grpc_python_out=tools/ tools/on_device_tests_gateway.proto + python -m grpc_tools.protoc -Itools/ --python_out=cobalt/tools/ --grpc_python_out=cobalt/tools/ cobalt/tools/on_device_tests_gateway.proto shell: bash - name: Set Up Cloud SDK uses: isarkis/setup-gcloud@40dce7857b354839efac498d3632050f568090b6 # v1.1.1 @@ -46,7 +46,7 @@ runs: GITHUB_WORKFLOW: ${{ github.workflow }} run: | set -uxe - python3 -u tools/on_device_tests_gateway_client.py \ + python3 -u cobalt/tools/on_device_tests_gateway_client.py \ --platform_json "${GITHUB_WORKSPACE}/src/.github/config/${{ matrix.platform}}.json" \ --filter_json_dir "${GITHUB_WORKSPACE}/src/cobalt/testing/${{ matrix.platform}}" \ --token ${GITHUB_TOKEN} \ diff --git a/tools/on_device_tests_gateway.proto b/cobalt/tools/on_device_tests_gateway.proto similarity index 100% rename from tools/on_device_tests_gateway.proto rename to cobalt/tools/on_device_tests_gateway.proto diff --git a/tools/on_device_tests_gateway_client.py b/cobalt/tools/on_device_tests_gateway_client.py similarity index 100% rename from tools/on_device_tests_gateway_client.py rename to cobalt/tools/on_device_tests_gateway_client.py From a7a759afecfb25aae3a66ebc9333a03511fbb777 Mon Sep 17 00:00:00 2001 From: Igor Sarkisov Date: Tue, 7 Jan 2025 14:36:08 -0800 Subject: [PATCH 13/14] Introduce "test_dimension" key --- .github/actions/on_device_tests/action.yaml | 1 + .github/config/android-arm.json | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index 478772a450ea8..816277766ebc0 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -5,6 +5,7 @@ runs: using: "composite" steps: - name: Install Requirements + # TODO (b/388329764) - set up requirements file. run: | pip3 install grpcio==1.38.0 grpcio-tools==1.38.0 shell: bash diff --git a/.github/config/android-arm.json b/.github/config/android-arm.json index 684725c6f75e2..6bfc85207a7e0 100644 --- a/.github/config/android-arm.json +++ b/.github/config/android-arm.json @@ -21,8 +21,10 @@ "sql_unittests", "url_unittests" ], - "gtest_device": "sabrina", - "gtest_lab": "maneki", + "test_dimensions": { + "gtest_device": "sabrina", + "gtest_lab": "maneki" + }, "test_on_device": true, "includes": [ { From 0b8c74248300c750082c0df2c97679a90f9f5a0b Mon Sep 17 00:00:00 2001 From: Igor Sarkisov Date: Wed, 8 Jan 2025 16:20:34 -0800 Subject: [PATCH 14/14] Log and XML file processing --- .github/actions/on_device_tests/action.yaml | 24 +++++++++++++++++++-- .github/workflows/main.yaml | 20 ++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/.github/actions/on_device_tests/action.yaml b/.github/actions/on_device_tests/action.yaml index 816277766ebc0..7bb7d04a6fb54 100644 --- a/.github/actions/on_device_tests/action.yaml +++ b/.github/actions/on_device_tests/action.yaml @@ -1,5 +1,9 @@ name: On Device Test description: Runs on-device tests. +inputs: + results_dir: + description: "Path to directory where test results are saved." + required: true runs: using: "composite" @@ -18,10 +22,8 @@ runs: - name: Set env vars run: | echo "PROJECT_NAME=$(gcloud config get-value project)" >> $GITHUB_ENV - # Test results and logs echo "GCS_RESULTS_PATH=gs://cobalt-unittest-storage/results/${{ matrix.name }}/${{ github.run_id }}" >> $GITHUB_ENV - # Dimension env if [ "${{ matrix.dimension }}" != "null" ]; then echo "DIMENSION=${{ matrix.dimension }}" >> $GITHUB_ENV @@ -72,3 +74,21 @@ runs: --gcs_result_path "${GCS_RESULTS_PATH}" \ trigger shell: bash + - name: Download ${{ matrix.platform }} Test Results + if: always() + env: + RESULTS_DIR: ${{ inputs.results_dir }} + run: | + set -uxe + mkdir -p "${GITHUB_WORKSPACE}/${RESULTS_DIR}" + cd "${GITHUB_WORKSPACE}/${RESULTS_DIR}" + gsutil cp "${GCS_RESULTS_PATH}/" . + echo "TEST_LOG=${GITHUB_WORKSPACE}/${RESULTS_DIR}/test_results.txt" >> $GITHUB_ENV + shell: bash + - name: Archive Test Logs + uses: actions/upload-artifact@v3 + if: always() + with: + name: Test log + path: ${{ env.TEST_LOG }}/ + diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 43c2ccb2aa8ee..35b68bf3ca5ca 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -246,6 +246,8 @@ jobs: platform: ${{ fromJson(needs.initialize.outputs.platforms) }} config: [devel] include: ${{ fromJson(needs.initialize.outputs.includes) }} + env: + TEST_RESULTS_DIR: ${{ matrix.name }}_test_results steps: - name: Checkout uses: kaidokert/checkout@v3.5.999 @@ -253,5 +255,21 @@ jobs: with: fetch-depth: 1 persist-credentials: false - - name: Run Tests (${{ matrix.shard }}) + - name: Run On-Device Tests (${{ matrix.shard }}) + id: on-device-tests uses: ./.github/actions/on_device_tests + with: + results_dir: ${{ env.TEST_RESULTS_DIR }} + - name: Process Test Results + if: | + always() && + ( + steps.on-device-tests.outcome == 'success' || + steps.on-device-tests.outcome == 'failure' + ) + uses: ./src/.github/actions/process_test_results + with: + results_dir: ${{ env.TEST_RESULTS_DIR }} + datadog_api_key: ${{ secrets.DD_API_KEY }} + is_postsubmit: ${{ github.event_name == 'schedule' || github.event_name == 'push' }} + continue-on-error: true